Mockito:在功能接口内监视函数调用?
Mockito: Spying function calls inside Functional interfaces?
Mockito 似乎无法监视函数式接口内的函数调用。假设我有一个带有服务的简单 Spring 启动应用程序:
@Service
public class TestService {
Function<Integer, Integer> mapping = this::add2;
Integer add2(Integer integer) {
return integer + 2;
}
}
还有一个测试:
@SpyBean
TestService testService;
@Test
public void mockitoTest2(){
doReturn(6).when(testService).add2(2);
System.out.println(testService.mapping.apply(2));
}
测试将 return 4 而不是 6。这是预期的,还是值得报告错误?
这是意料之中的。 Mockito 通过制作 浅拷贝 创建间谍,方法引用 this::add2
被复制,同时保留对旧 this
.
的引用
TestService myTestService = new TestService();
TestService mySpy = Mockito.spy(myTestService);
在此示例中,mySpy
是 TestService 的生成子类的一个实例,它的所有可重写方法都被重写以委托给 Mockito,并且所有它的实例状态是从 myTestService
浅层复制而来的。这意味着myTestService.mapping == mySpy.mapping
,这也意味着在函数中捕获对this
(意思是myTestService
)的引用被复制过来。
应用于实例的方法引用捕获该实例,如 "Kinds of Method References" 下的 the Oracle page on Method References。接收 add2
调用的对象是原始对象,而不是间谍,因此您得到原始行为 (4) 而不是受间谍影响的行为 (6)。
这应该有点直观:您可以调用 Function<Integer, Integer>
而无需传递 TestService 实例,因此 Function 包含对 TestService 实现的隐式引用是非常合理的。您看到此行为是因为间谍实例的状态是从真实实例复制的 在 函数初始化并存储 this
之后。
考虑这个替代方案,您可以在 TestService 上定义它:
BiFunction<TestService, Integer, Integer> mapping2 = TestService::add2;
这里,函数 mapping2
不应用于特定对象,而是应用于传入的任何 TestService 实例。因此,您的测试将调用此:
@Test
public void mockitoTest2(){
doReturn(6).when(testService).add2(2);
System.out.println(testService.mapping2.apply(testService, 2));
}
...并且因为您正在传递您的间谍 testService
,它将处理对 add2
的虚拟方法调用并调用间谍上设置的行为(返回 6)。没有隐式保存 this
,因此您的函数按预期工作。
另请参阅:
Mockito 似乎无法监视函数式接口内的函数调用。假设我有一个带有服务的简单 Spring 启动应用程序:
@Service
public class TestService {
Function<Integer, Integer> mapping = this::add2;
Integer add2(Integer integer) {
return integer + 2;
}
}
还有一个测试:
@SpyBean
TestService testService;
@Test
public void mockitoTest2(){
doReturn(6).when(testService).add2(2);
System.out.println(testService.mapping.apply(2));
}
测试将 return 4 而不是 6。这是预期的,还是值得报告错误?
这是意料之中的。 Mockito 通过制作 浅拷贝 创建间谍,方法引用 this::add2
被复制,同时保留对旧 this
.
TestService myTestService = new TestService();
TestService mySpy = Mockito.spy(myTestService);
在此示例中,mySpy
是 TestService 的生成子类的一个实例,它的所有可重写方法都被重写以委托给 Mockito,并且所有它的实例状态是从 myTestService
浅层复制而来的。这意味着myTestService.mapping == mySpy.mapping
,这也意味着在函数中捕获对this
(意思是myTestService
)的引用被复制过来。
应用于实例的方法引用捕获该实例,如 "Kinds of Method References" 下的 the Oracle page on Method References。接收 add2
调用的对象是原始对象,而不是间谍,因此您得到原始行为 (4) 而不是受间谍影响的行为 (6)。
这应该有点直观:您可以调用 Function<Integer, Integer>
而无需传递 TestService 实例,因此 Function 包含对 TestService 实现的隐式引用是非常合理的。您看到此行为是因为间谍实例的状态是从真实实例复制的 在 函数初始化并存储 this
之后。
考虑这个替代方案,您可以在 TestService 上定义它:
BiFunction<TestService, Integer, Integer> mapping2 = TestService::add2;
这里,函数 mapping2
不应用于特定对象,而是应用于传入的任何 TestService 实例。因此,您的测试将调用此:
@Test
public void mockitoTest2(){
doReturn(6).when(testService).add2(2);
System.out.println(testService.mapping2.apply(testService, 2));
}
...并且因为您正在传递您的间谍 testService
,它将处理对 add2
的虚拟方法调用并调用间谍上设置的行为(返回 6)。没有隐式保存 this
,因此您的函数按预期工作。
另请参阅: