我有一个我这样嘲笑的类:
@Mock
private MyClass1 mockMyClass1;
假设这个类看起来像这样:
public class MyClass1 {
@Autowired
private MyInnerClass myInnerClass;
}
当我模拟MyClass1
时,MyInnerClass
将被初始化为null
。是否可以在另一个模拟对象的情况下初始化该私有字段?我希望myInnerClass
像这样模拟:
@Mock
private MyInnerClass myInnerClass;
如果我使用以下代码:
@InjectMocks
private MyClass1 mockMyClass1;
@Mock
private MyInnerClass myInnerClass
这会将MyClass1
内部的私有MyInnerClass
初始化为模拟对象,但是这种方式mockMyClass1
不再是模拟本身,不是吗(我只是在真实类中注入一个模拟对象,就像@Autowired
将在其中注入真实对象一样(?如果我对@InjectMock
和@Mock
的理解是错误的,你能纠正我的逻辑吗?另外,如何将模拟对象注入另一个模拟对象(不使用setter/constructors(?
你误解了什么是模拟。
当你在模拟MyClass1
时,MyInnerClass
类型的内部字段对于被模拟的对象不再存在。因此,尝试在模拟中注入一些东西是没有意义的。
模拟是通过说出当您与之交互时应该做什么来控制的。你存根它的公共方法来做你想让他们做的事情。你给行为。唯一的默认行为(可能特定于 Mockito(是返回 null
如果你没有配置 mock(但请注意它不返回null
,因为某些内部变量null
,它返回它是因为 Mockito 决定这就是它应该返回的; 也许另一个模拟框架决定它应该抛出一个异常, 谁知道呢?
例如,假设您的真实类是:
class MyClass1 {
private MyInnerClass myInnerClass;
public MyInnerClass getMyInnerClass() {
return myInnerClass;
}
}
现在考虑mock
该类的模拟。如果你调用mock.getMyInnerClass()
,它不是要调用的真正方法。它将返回的不是myInnerClass
的值。它将返回null
,或者如果您已将该方法存根
when(mock.getMyInnerClass()).thenReturn(something);
然后它将返回something
.
所以回答你的问题:你不能这样做,因为这不是模拟的工作方式。
应该使用InjectMocks注释(要了解原因,你可以阅读这篇文章(。
您可以只为 MyClass1 实现自动连线构造函数,而不是自动连线字段。然后,您可以简单地将MyInnerClass模拟引用作为构造函数参数传递。