是改变对象的模拟



我有以下结构

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);

相关内容

  • 没有找到相关文章

最新更新