在测试期间注入@Autowired私有字段

2022-08-31 11:01:21

我有一个组件设置,它本质上是应用程序的启动器。它的配置如下:

@Component
public class MyLauncher {
    @Autowired
    MyService myService;

    //other methods
}

MyService使用Spring注释进行注释,并自动连接到我的启动器类中,没有任何问题。@Service

我想为MyLauncher编写一些jUnit测试用例,为此我开始了这样的课程:

public class MyLauncherTest
    private MyLauncher myLauncher = new MyLauncher();

    @Test
    public void someTest() {

    }
}

是否可以为 MyService 创建一个 Mock 对象,并将其注入到测试类中的 myLauncher 中?我目前在myLauncher中没有getter或setter,因为Spring正在处理自动布线。如果可能的话,我希望不必添加 getter 和 setter。我能否告诉测试用例使用 init 方法将模拟对象注入自动连接变量?@Before

如果我完全错了,请随时说出来。我还是新手。我的主要目标是有一些Java代码或注释,将模拟对象放在该变量中,而不必编写setter方法或使用文件。我宁愿维护文件中测试用例的所有内容,而不必仅为我的测试维护单独的应用程序内容。@AutowiredapplicationContext-test.xml.java

我希望将Mockito用于模拟对象。过去,我通过使用 和 创建对象来执行此操作。org.mockito.MockitoMockito.mock(MyClass.class)


答案 1

你绝对可以在测试中在MyLauncher上注入模拟。我相信,如果你展示你正在使用的模拟框架,有人会很快提供答案。使用mockito,我会考虑使用@RunWith(MockitoJUnitRunner.class)并为myLauncher使用注释。它看起来有点像下面的内容。

@RunWith(MockitoJUnitRunner.class)
public class MyLauncherTest
    @InjectMocks
    private MyLauncher myLauncher = new MyLauncher();

    @Mock
    private MyService myService;

    @Test
    public void someTest() {

    }
}

答案 2

接受的答案(使用和)很棒。但是,如果你想要一些更轻量级的东西(没有特殊的JUnit运行器),并且不那么“神奇”(更透明),特别是对于偶尔使用,你可以直接使用内省来设置私有字段。MockitoJUnitRunner@InjectMocks

如果你使用Spring,你已经有一个实用程序类:org.springframework.test.util.ReflectionTestUtils

使用非常简单:

ReflectionTestUtils.setField(myLauncher, "myService", myService);

第一个参数是目标 Bean,第二个参数是(通常是私有)字段的名称,最后一个是要注入的值。

如果您不使用Spring,那么实现这样的实用程序方法就非常简单了。这是我在找到这个Spring类之前使用的代码:

public static void setPrivateField(Object target, String fieldName, Object value){
        try{
            Field privateField = target.getClass().getDeclaredField(fieldName);
            privateField.setAccessible(true);
            privateField.set(target, value);
        }catch(Exception e){
            throw new RuntimeException(e);
        }
    }

推荐