当前位置: 首页 > 面试题库 >

Mockito when()调用如何工作?

吕胤
2023-03-14
问题内容

给出以下Mockito语句:

when(mock.method()).thenReturn(someValue);

考虑到嘲笑方法将返回值传递给when(),Mockito如何为该嘲笑创建代理?我想这会使用一些CGLib的东西,但是有兴趣知道这在技术上是如何完成的。


问题答案:

简短的答案是,在您的示例中,的结果mock.method()将是类型合适的空值;Mockito通过代理,方法拦截和类的共享实例使用间接方式,MockingProgress以确定对模拟方法的调用是用于存根还是重放现有的存根行为,而不是通过的返回值传递有关存根的信息。一种嘲笑的方法。

几分钟后,对微型代码进行了简短的分析。注意,这是一个非常粗糙的描述-这里有很多细节。我建议您自己检查github上的源代码。

首先,当您使用类的mock方法模拟一个类时Mockito,实际上是这样:

  1. Mockito.mockorg.mockito.internal.MockitoCore默认的模拟设置作为参数传递给.mock。
  2. MockitoCore.mock代表org.mockito.internal.util.MockUtil.createMock
  3. MockUtil类使用ClassPathLoader类来获得的实例MockMaker用于创建模拟。默认情况下,使用CgLibMockMaker类。
  4. CgLibMockMaker使用从JMock借用的类,该类ClassImposterizer处理创建模拟。所使用的“魔术的Mockito”键片的MethodInterceptor用于创建模拟:所述的MockitoMethodInterceptorFilter以及MockHandler实例,包括的实例的链MockHandlerImpl。方法拦截器将调用传递给MockHandlerImpl实例,该实例实现在对某个模拟调用某个方法时(例如,搜索是否已记录答案,确定该调用是否代表新的存根等)应应用的业务逻辑。默认状态是,如果尚未为正在调用的方法注册存根,则将返回类型合适的空值。
    现在,让我们看一下示例中的代码:
when(mock.method()).thenReturn(someValue)

这是此代码执行的顺序:

mock.method()
when(<result of step 1>)
<result of step 2>.thenReturn

理解发生了什么的关键是当调用模拟方法上的方法时会发生什么:向方法拦截器传递有关方法调用的信息,并委托给它的MockHandler实例链,最终将实例委托给MockHandlerImpl#handle。在期间MockHandlerImpl#handle,模拟处理程序创建的实例OngoingStubbingImpl并将其传递给共享MockingProgress实例。

在when调用之后调用该方法时method(),它将委托给MockitoCore.when,后者将调用stub()同一类的方法。此方法从MockingProgress模拟method()调用写入的共享实例中解压缩正在进行的存根,然后将其返回。然后thenReturnOngoingStubbing实例上调用方法。



 类似资料:
  • 鉴于以下Mockito语句: 假设mock.method()语句将返回值传递给when(),Mockito如何为mock创建代理?我想这使用了一些CGLib的东西,但我想知道这是如何在技术上完成的。

  • 我试图理解过滤器链接。正如这个问题所定义的 所有过滤器都被链接(按照它们在web.xml中定义的顺序)。chain.doFilter()正在进行到链中的下一个元素。链的最后一个元素是目标资源/servlet。 我很想知道容器中的场景背后,容器是如何处理过滤器链接的。有人能解释一下过滤器链接是如何在容器内处理的吗?

  • 我一直在尝试建立一个PHP网站。不管我怎么努力,我都无法让gettext开始工作。 我正在运行一个ubuntu apache服务器上的流浪框,我需要的所有区域设置都是可用的和生成的(使用区域设置-a检查)。 已安装并启用Gettext(使用phpinfo()检查) 这是我的PHP: 这是我的/vagrant/build/locale/en_US/LC_MESSAGES/en_US。采购订单文件:

  • 问题内容: sleep()是Thread类的静态方法。从多个线程调用时,它是如何工作的。以及如何找出当前的执行线程。? 或者可能是更通用的问题?如何从不同线程调用静态方法?不会有并发问题吗? 问题答案: 如何找出当前的执行线程? 不必。它仅调用操作系统,该操作系统始终使调用它的线程休眠。

  • 我开始为Python使用vscode。我有一个简单的测试程序。我想在debug下运行它,我需要设置运行的工作目录。 我该怎么做/在哪里做?

  • 我想要一个方法,它从处理中调用一个方法,并返回可能产生的任何值。 我已经有了一个方法,它从当前实例上的超类中调用一个方法,所以我认为这一方法的一个实现就是用我已有的方法创建一个草图 然后做一些像 但是我得到了以下异常,因为我没有调用或 异常线程"main"java.lang.NullPointerExcema 在processing.core.PApplet.textWidth(PApplet.j