我有以下结构
public class A{...}
public class B extends A{
private C cObject;
private Object otherValue;
B(){
cObject = new C(this);
}
}
public class C{
private B bObject;
C(B bObject){
this.bObject = bObject;
}
}
我想测试类B的一个方法,我使用mockito是因为我需要模拟B的另一个方法来测试我想测试的方法。所以在我的测试中,我声明B对象为@Spy
,然后我调用MockitoAnnotations.initMocks(this);
,最后我使用doReturn().when().method();
现在我运行测试,它失败了。当我调试它时,我感到惊讶,我意识到当我在对象B中时,字段otherValue
的值例如X
,但当我在C中时,this.bObject.otherValue
的值不是X
而是null
。
既然我用new C(this);
在B中创建了对象C, B和C不应该是相同的对象,因此包含相同的值吗?
注意:我也试过没有监视对象和嘲笑方法,它工作,所以真正的问题是:
当我窥探它时,Mockito是否用另一个对象替换我的对象?在这种情况下,我该怎么做才能让它起作用呢?
EDIT一个更简单的解释可能是:我想测试一个对象B,这个对象B创建了一个对象C的实例,并将其自身(this)作为参数传递。我需要监视对象B,所以我在测试中创建了B的实例,然后调用MockitoAnnotations.initMocks(this);
。两个对象(测试中的一个和C实例中的一个)在调用之后仍然是相同的对象还是用新的对象替换它?
B
实例将在被监视之前被构造,因此C
接收到的引用是实际的 B
对象,而不是被监视的实例。
你正在向监视实例添加行为,这实际上是一个与C.bObject
不同的对象,因此行为不适用。同样,设置b.otherValue
也不会导致设置b.cObject.bObject.otherValue
。
您可以看到这些是不同的对象—假设存在默认的toString
:
final B b = Mockito.spy(new B());
System.out.println("spied: " + b);
System.out.println("b.cObject.bObject: " + b.cObject.bObject);
它应该产生如下内容:
spied: B$$EnhancerByMockitoWithCGLIB$$999ce15d@7a187814
b.cObject.bObject: B@5c73a7ab
也许你可以使用反射来设置b.cObject.bObject
字段为被监视的实例?例如:
final Field f = C.class.getDeclaredField("bObject");
f.setAccessible(true);
f.set(b.cObject, b);