我有类似
的东西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的方法时,这个内部对象用于给我基于我需要的结果我在建造过程中提供的价值。答案 0 :(得分:1)
以上代码无效。
1)@InjectMocks
使用了很多“魔法”,并且没有必要采用最清晰,可调试的方式来设置被测对象的模拟。
在引擎盖下,它尝试了多种方法:构造函数注入,属性设置器注入,现场注入
但如果它没有注入,那就不会报告失败:
如果以下任何策略失败,那么Mockito将不会报告 失败;即你必须自己提供依赖。
作为替代方案,您可以明确设置被测对象的依赖关系。
2)侧面但重要的注意事项:使用小写作为首字母命名变量。用类名命名它们是不可读和传统的。
3)这没有意义:
@Mock
Foo2 Foo2 = new Foo2(ObjectA);
您实例化Foo2
,然后由Mockito模拟替换
模拟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 ...
}
答案 1 :(得分:0)
尽管代码风格,但你遇到的问题是Foo2
并不是真正的模拟,因为你明确地实例化它。如果您确实想要使用Foo2
实例实例化的“真实”Object2
实例,请考虑在@Spy
上使用Foo2
注释。然后,@InjectMocks
注释应该按照您的预期进行。