Mockito 监视具有内部方法引用的类



在使用@Spy注释监视服务并让 Mockito 创建显式调用构造函数的服务器诗句时,我看到了不同的行为。

public class MyService {
private final Supplier<String> methodBCall;
public MyService() {
methodBCall = this::methodB;
}
public void methodA() {
methodBCall.get();
}
public String methodB() {
return "methodB";
}
}
@RunWith(MockitoJUnitRunner.class)
public class MyTest {
@Spy
private MyService myService1;
@Spy
private MyService myService2 = new MyService();
@Test
public void testSucceeds() {
myService1.methodA();
verify(myService1, times(1)).methodA();
verify(myService1, times(1)).methodB();
}
@Test
public void testFails() {
myService2.methodA();
verify(myService2, times(1)).methodA();
verify(myService2, times(1)).methodB();
}
}

失败的测试失败,并显示

Wanted but not invoked:
myService2.methodB();
-> at com.phemi.services.policy.impl.MyTest.testFails

为什么这两者的行为不同?Mockito做了什么来初始化myService1,使其能够监视方法B?

这是一个简化的示例,在我的情况下,要正确测试我的服务,我需要用参数调用它的构造函数(因此不能将@Spy与默认构造函数一起使用(。但是,当我这样做时,我无法正确验证方法调用。

myService2上的spy仅在构造对象后创建,因此在constructor中调用方法没有帮助,因为它包含对初始对象(不是spy对象(的方法引用。

当您比较两种情况的实现时,差异变得更加明显:

Mockito.spy(Class)

public static <T> T spy(Class<T> classToSpy) {
return MOCKITO_CORE.mock(classToSpy, withSettings()
.useConstructor()
.defaultAnswer(CALLS_REAL_METHODS));
}

Mockito.spy(Object)

public static <T> T spy(T object) {
return MOCKITO_CORE.mock((Class<T>) object.getClass(), withSettings()
.spiedInstance(object)
.defaultAnswer(CALLS_REAL_METHODS));
}

如您所见,第一种情况基于类(如果未创建@Spy实例则使用该类(,首先创建一个模拟并在模拟对象上使用构造函数。

在第二种情况下,不考虑构造函数,而是创建不同的实例。

最新更新