[英]Mockito Spying on Class that has an internal method reference
I'm seeing a different in behaviour when spying on a service using the @Spy annotation and having Mockito create the Server verses explicitly calling the constructor. 在使用@Spy注释监视服务并让Mockito创建显式调用构造函数的Server诗句时,我发现行为有所不同。
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();
}
}
The failing test fails with 测试失败的原因是
Wanted but not invoked:
myService2.methodB();
-> at com.phemi.services.policy.impl.MyTest.testFails
Why do these two behave differently? 为什么这两个行为不同? What is Mockito doing to initialize myService1 that enables it to spy on methodB?
Mockito在初始化myService1使其能够监视methodB时在做什么?
This is a simplified example, in my case to test my service properly I need to call its constructor with an argument (and so cannot use the @Spy with a default constructor). 这是一个简化的示例,在本例中,为了正确测试我的服务,我需要使用参数调用其构造函数(因此不能将@Spy与默认构造函数一起使用)。 However, when I do that I cannot properly verify method calls.
但是,当我这样做时,我无法正确验证方法调用。
The spy
on myService2
is only created after the object has been constructed, so having a method call in the constructor
is not helpfull as it contains a method reference to the initial object (which is not the spy
object). 的
spy
上myService2
对象已经被构造之后,所以具有在一个方法调用时才创建constructor
并不有益的,因为它包含的方法参照初始对象(其不是spy
对象)。
The difference becomes more evident when you compare the implementation for both cases: 当您比较两种情况的实现时,差异变得更加明显:
public static <T> T spy(Class<T> classToSpy) {
return MOCKITO_CORE.mock(classToSpy, withSettings()
.useConstructor()
.defaultAnswer(CALLS_REAL_METHODS));
}
public static <T> T spy(T object) {
return MOCKITO_CORE.mock((Class<T>) object.getClass(), withSettings()
.spiedInstance(object)
.defaultAnswer(CALLS_REAL_METHODS));
}
As you can see the first case, based on a class (which is used if no instance for @Spy
was created), creates a mock first and uses the constructor on the mocked object. 如您所见,第一种情况基于一个类(如果未创建
@Spy
实例,则使用@Spy
),首先创建一个模拟并在模拟对象上使用构造函数。
In the second case the constructor is not considered instead a different instance is created. 在第二种情况下,不考虑构造函数,而是创建了一个不同的实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.