我在 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/