我正在使用Mockito的@Mock
和@InjectMocks
注释将依赖项注入私有字段,这些字段使用Spring @Autowired
进行注释:
@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
@Mock
private SomeService service;
@InjectMocks
private Demo demo;
/* ... */
}
和
public class Demo {
@Autowired
private SomeService service;
/* ... */
}
现在我想将真正的对象注入私有@Autowired
字段(没有setter)。这是可能的还是机制仅限于注射模拟?
答案 0 :(得分:245)
使用@Spy
注释
@RunWith(MockitoJUnitRunner.class)
public class DemoTest {
@Spy
private SomeService service = new RealServiceImpl();
@InjectMocks
private Demo demo;
/* ... */
}
Mockito会将所有具有@Mock
或@Spy
注释的字段视为注入@InjectMocks
注释注释实例的潜在候选项。在上面的例子中,'RealServiceImpl'
实例将被注入'demo'
有关详细信息,请参阅
答案 1 :(得分:2)
在Spring中,有一个专用的实用程序ReflectionTestUtils
用于此目的。以特定实例为例,并注入到字段中。
@Spy
..
@Mock
..
@InjectMock
Foo foo;
@BeforeEach
void _before(){
ReflectionTestUtils.setField(foo,"bar", new BarImpl());// `bar` is private field
}
答案 2 :(得分:1)
Mockito不是DI框架,甚至DI框架也鼓励构造函数注入而不是字段注入。
因此,您只需声明一个构造函数即可设置被测类的依赖项:
@Mock
private SomeService serviceMock;
private Demo demo;
/* ... */
@BeforeEach
public void beforeEach(){
demo = new Demo(serviceMock);
}
在一般情况下使用Mockito spy
是一个糟糕的建议。它使测试类变脆,不简单并且容易出错:真正被嘲笑的是什么?真正经过测试的是什么?
@InjectMocks
和@Spy
还会损害整体设计,因为它会鼓励classes肿的班级和班级中的混合职责。
read the spy()
javadoc,请先盲目使用(重点不是我的):
创建真实对象的间谍。间谍会调用 real 方法,除非 他们被打断了。真正的间谍应该小心使用,并且 ,例如在处理旧版代码时。
与往常一样,您将阅读
partial mock warning
:对象 面向程序设计通过划分复杂度来解决复杂度 分成单独的特定SRPy对象。部分模拟如何适应 这个范式?好吧,事实并非如此……部分模拟通常意味着 复杂性已移至同一方法上的另一种方法 宾语。在大多数情况下,这不是您要设计自己的方式 应用。但是,在少数情况下,局部模拟会派上用场: 使用代码,您无法轻易更改(第三方接口,临时 重构旧代码等。)但是,我不会使用部分模拟 用于新的,测试驱动的和精心设计的代码。
答案 3 :(得分:1)
我知道这是一个古老的问题,但是在尝试注入字符串时我们遇到了同样的问题。因此,我们发明了一种JUnit5 / Mockito扩展,可以完全满足您的需求:https://github.com/exabrial/mockito-object-injection
编辑:
@InjectionMap
private Map<String, Object> injectionMap = new HashMap<>();
@BeforeEach
public void beforeEach() throws Exception {
injectionMap.put("securityEnabled", Boolean.TRUE);
}
@AfterEach
public void afterEach() throws Exception {
injectionMap.clear();
}