java - Mockito:是否可以将 mock 与方法名称结合起来在 when() 调用中创建 methodCall?

标签 java class reflection methods mockito

我在 StackOverflow 上的第一个问题。我希望能够做类似的事情:

SomeClass mock = mock(SomeClass.class);

String methodName = "someMethod";或方法方法 = ...someMethod...

这两个东西(mock 和方法)将结合起来执行以下操作:

when(mock.someMethod()).thenReturn(null);

当然,'null' 值会根据我的需要进行相应更改,但我试图确定两件事:

1) 是否有可能在 Java 中执行类似this 的操作? This = 将类对象和方法组合到 methodCall 中。

2) 我该怎么做?

我一直在研究这个,但我找不到任何东西。问题是,即使这适用于常规类和常规方法(someClass 和 someMethod 会一起执行 someClass.someMethod()),请记住,这必须适用于模拟对象 用于 when() 调用。

回答:when(method.invoke(mock)).thenReturn("Hello world.");是正确的语法并且反射确实在 when() 调用中起作用。谢谢凯文韦尔克!

最佳答案

既然你基本上是让我重新发布我的评论,根据你的回复修改,作为答案,这里是:

尝试像这样使用反射:

when(method.invoke(mock)).thenReturn("Hello world.");

尽管如此,我不确定这对您有何作用,因为您不能模拟/监视类 Method(它是最终的)。 Mockito 的 when() 仅适用于模拟或 spy 。如果这真的对你有用,你能发布更多细节吗?

如果它不起作用,您可以——正如我在 OP 的评论中所建议的那样——走 CGLib 路线并绕过 Mockito。这真的没有乍看起来那么难。在我的 OSS 项目中 Funcito (不是 模拟框架),我剥离了很多 Mockito CGLib 代理代码并根据我的需要重写了它。它为代理类和拦截方法调用的世界提供了一个更简单的 View 。

对评论的补充回复 我知道这是如何为你工作的,但我不确定你是否真的理解它是如何工作的。这可能很重要,因为 Mockito 本身工作方式的 future 变化可能会导致您的解决方案在未来崩溃。从本质上讲,它起作用的原因几乎是偶然的,但它确实会起作用。

when() 应该工作的方式是括号之间发生的是对先前创建的 Mockito 生成的模拟或 spy 的方法调用,这只是类,而不是类的真实实例。代理具有特殊的逻辑,可以拦截伪造的代理方法调用,并将其添加到已注册的代理方法调用列表中(它存储在称为 IOngoingStubbing 或类似的东西中)供以后使用。由于 Java 在调用方法之前评估参数,这保证了代理方法调用在实际执行 when() 方法之前得到注册/记住。 when() 所做的是弹出此 IOngoingStubbing,然后它成为调用 thenReturns() 的对象。

您没有“正确”使用它,但它仍然适用于您。如何?好吧,所有需要发生的事情是需要调用代理上的方法,以便在执行 when() 之前在 IOngoingStubbing 中注册。您不是直接调用代理上的方法,而是通过将代理传递给 Method.invoke() 间接调用代理上的方法。因此满足条件,并且 when() 已经在 IOngoingStubbing 中注册了一个代理方法调用。

你可以在下面的代码中看到同样的“偶然”的快乐,一开始看起来毫无意义,直到你意识到 Mockito 的工作原理:

@Test
public void testSomething() throws Exception {
    List listMock = mock(List.class);
    Method m = List.class.getDeclaredMethod("get", int.class);
    m.invoke(listMock, Mockito.anyInt());

    when(null).thenReturn("Hello World");  // Huh? passing null?

    assertEquals("Hello World", listMock.get(0)); // works!
}

上面的测试居然通过了!即使 when 的参数为 null,重要的是代理(即模拟)实例在调用 when 语句之前调用了正确的方法。

虽然 Mockito 不太可能改变幕后工作的基本方式,但在未来的某个时候它仍然有可能被打破。就像我说的,它起作用或多或少是一个幸运的意外。只要您了解它的工作方式和所涉及的风险,您就会拥有更多的力量。

关于java - Mockito:是否可以将 mock 与方法名称结合起来在 when() 调用中创建 methodCall?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10124482/

相关文章:

java - 使用路径列表从 SSH 查询大量文件

使用 RabbitTemplate 发布消息时出现 java.lang.IllegalArgumentException

java - 去除除法中的小数

python - 如何检测嵌套列表的哪些元素发生了变化? (Python)

java - 如何在 protected Java 类上实现接口(interface)

java - 使用 Gson 加载对象

Java Reflection - 从对象获取类型以实例化泛型

java - 将项目添加到 ArrayList Java Android 时出错

java - 无法将主类与 Netbeans 中的其他类连接

反射(reflection):检索属性值的不同方式