在使用@InjectMocks注入模拟对象内部之前初始化它
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在使用@InjectMocks注入模拟对象内部之前初始化它相关的知识,希望对你有一定的参考价值。
我有类似的东西
private static final CustomObject ObjectA = new CustomObject();
@Mock
Foo1 foo1;
@Mock
Foo2 Foo2 = new Foo2(ObjectA);
@Mock
Foo3 foo3;
@InjectMocks
ContainerClass container;
我想在将Object注入容器之前用ObjectA初始化Foo2。上面的代码不起作用。
编辑:我试图模拟Foo2,但有一个Foo2的内部对象,我想用一个真实对象初始化,所以当我调用Foo2的方法时,这个内部对象用于给我根据值我需要的结果在施工期间提供。
上面的代码不起作用。
1)@InjectMocks
使用了很多“魔法”,并且没有必要采用最清晰,可调试的方式来设置被测对象的模拟。
在引擎盖下,它尝试了多种方法:构造函数注入,属性设置器注入,字段注入。
但如果它无法注入,则不会报告失败:
如果以下任何一种策略失败,那么Mockito将不会报告失败;即你必须自己提供依赖。
作为替代方案,您可以明确设置被测对象的依赖关系。
2)侧面但重要的注意事项:使用小写作为首字母命名变量。使用类名命名它们是不可读和常规的。
3)这没有意义:
@Mock
Foo2 Foo2 = new Foo2(ObjectA);
你实例化Foo2
然后被Mockito mock替换。
嘲弄Foo2
的行为,但让它的ObjectA
依赖是一个没有模拟的对象并不是真正的逻辑。
通过这样做,您不会真正模拟被测对象的依赖关系,因为您的调用模式是:
测试对象 - > mock dep1 - >真实对象dep2
在这种情况下,编写集成测试(没有模拟)更有意义。
当您对ContainerClass
进行单元测试时,您将仅测试ContainerClass
行为。
你希望获得结果的ObjectA
方法应该是Foo2
调用ObjectA
,你在测试中模拟了对Foo2
的调用。
请注意,如果模拟其调用者的方法,则无需模拟ObjectA
。
这是一个例子:
public class Foo2{
private ObjectA objectA;
public Foo2(ObjectA objectA){
this.objectA = objectA;
}
public Bar callObjectA(){
return objectA.foo();
}
}
你需要在这里模拟的是callToObjectA()
。
@Mock
Foo1 foo1;
@Mock
Foo2 foo2;
@Test
public void myMethod(){
ContainerClass container = new ContainerClass(foo1, foo2);
Bar mockedBar = new Bar(....);
Mockito.when(foo2.callObjectA()).thenReturn(mockedBar);
// invoke the method under test
container.myMethod();
// assertions ...
}
代码风格尽管如此,你遇到的问题是Foo2
并不是真正的模拟,因为你明确地实例化它。如果你真的想使用用Foo2
实例实例化的“真实”Object2
实例,那么考虑在@Spy
上使用Foo2
注释。然后,@InjectMocks
注释应该做你期望的。
以上是关于在使用@InjectMocks注入模拟对象内部之前初始化它的主要内容,如果未能解决你的问题,请参考以下文章
如何在spring boot中将@Value属性从application.properties注入@InjectMocks?
Kotlin,Spring book,Mockito,@InjectMocks,使用与创建的不同的模拟
在 Mockito Junit 中 @InjectMocks 后为空