Mockito:监视功能接口内部的函数调用吗? [英] Mockito: Spying function calls inside Functional interfaces?

查看:363
本文介绍了Mockito:监视功能接口内部的函数调用吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Mockito似乎无法监视Functional接口内部的函数调用.假设我有一个带有服务的简单Spring Boot应用程序:

Mockito doesn't seem to be able to spy on function calls inside Functional interfaces. Suppose I have a simple Spring Boot App with a service:

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

}

测试将返回4而不是6.这是预期的还是值得进行错误报告?

The test will return 4 instead of 6. Is this expected, or worth a bug report?

推荐答案

这是预期的. Mockito通过创建浅拷贝来创建间谍,并且在保留对旧this的引用的同时,复制了方法引用this::add2.

This is expected. Mockito creates a spy by making a shallow copy, and the method reference this::add2 gets copied over while keeping the reference to the old this.

TestService myTestService = new TestService();
TestService mySpy = Mockito.spy(myTestService);

在此示例中,mySpy TestService生成的子类的实例,该实例的所有可重写方法都被重写以委派给Mockito,并且其所有实例状态都从myTestService.这意味着myTestService.mapping == mySpy.mapping,这也意味着对this的引用(意味着myTestService)在函数中被捕获.

In this example, mySpy is an instance of a generated subclass of TestService, which has all of its overridable methods overridden to delegate to Mockito, and all of its instance state shallow-copied from myTestService. This means that myTestService.mapping == mySpy.mapping, which also implies that the reference to this (meaning myTestService) is captured in the Function is copied over.

应用于实例的方法引用捕获该实例,如 方法参考种类"下方法参考"上的Oracle页面.接收add2调用的对象是原始对象,而不是间谍,因此您得到的是原始行为(4),而不是受到间谍影响的行为(6).

Method references applied to an instance capture that instance, as on the Oracle page on Method References under "Kinds of Method References". The object that receives the add2 call is the original, not the spy, so you get the original behavior (4) and not the spy-influenced behavior (6).

这应该有点直观:您可以在不传递TestService实例的情况下调用Function<Integer, Integer>,因此,该Function包含对TestService实现的隐式引用是很合理的.您正在看到这种现象,因为在初始化函数并存储了this之后,间谍实例的状态是从真实实例 复制而来.

This should be somewhat intuitive: You can call the Function<Integer, Integer> without passing around a TestService instance, so it's pretty reasonable that the Function contains an implicit reference to a TestService implementation. You're seeing this behavior because the spy instance has its state copied from a real instance after the Function is initialized and this is stored.

考虑此替代方法,您可以在TestService上进行定义:

Consider this alternative, which you could define on TestService:

BiFunction<TestService, Integer, Integer> mapping2 = TestService::add2;

这里,函数mapping2不适用于特定对象,而是适用于传入的TestService的任何实例.因此,您的测试将调用此函数:

Here, the function mapping2 doesn't apply to a particular object, but instead applies to any instance of TestService passed in. Consequently, your test would call this:

@Test
public void mockitoTest2(){
    doReturn(6).when(testService).add2(2);
    System.out.println(testService.mapping2.apply(testService, 2));
}

...并且因为您要传入间谍testService,所以它将处理对add2的虚拟方法调用并调用对间谍设置的行为(返回6).没有隐式保存的this,因此您的功能可以按预期工作.

...and because you are passing in your spy testService, it will handle the virtual method call to add2 and invoke the behavior set on the spy (returning 6). There is no implicitly-saved this, so your function works as you'd expect.

另请参见: 可运行的Mockito:需要但未调用?

这篇关于Mockito:监视功能接口内部的函数调用吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆