Mockito:是否有可能将mock与方法名称结合起来在when()调用中创建一个methodCall?

And*_*rew 7 java reflection methods class mockito

我在StackOverflow上的第一个问题.我希望能够做到这样的事情:

SomeClass mock = mock(SomeClass.class);

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

这两件事(模拟和方法)将结合起来执行以下操作:

当(mock.someMethod())thenReturn(空).

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

1),它甚至有可能做一些像这样在Java中? =将类对象和方法组合到methodCall中.

2)我怎么做这样的事情?

我无休止地研究了这个,我找不到任何东西.问题是即使这适用于常规类和常规方法(someClass和someMethod会聚在一起做someClass.someMethod()),请记住,这必须与模拟对象一起使用才能在when中使用( )打电话.

答案:when(method.invoke(mock)).thenReturn("Hello world."); 是正确的语法和反射确实在when()调用内工作.谢谢Kevin Welker!

Kev*_*ker 7

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

尝试使用反射,如:

when(method.invoke(mock)).thenReturn("Hello world.");
Run Code Online (Sandbox Code Playgroud)

虽然,我不确定这对你有什么用,因为你不能模拟/间谍课Method(这是最后的).Mockito when()只适用于模拟或间谍.如果这真的对你有用,你可以发布更多细节吗?

如果它不起作用,你可以 - 正如我在OP中的评论中所建议的那样 - 去CGLib路线并绕过Mockito.它首先看起来并不那么困难.在我的OSS项目Funcito(不是一个模拟框架)中,我删除了很多Mockito CGLib代理代码并根据我的需要重写了它.它为代理类的世界和拦截方法调用提供了更简单的视图.

对评论的额外回应 我看到这对你有用,但我不确定你是否真的理解它是如何工作的.这可能很重要的原因是因为Mockito本身工作方式的未来变化可能会在未来破坏您的解决方案.从本质上讲,它起作用的原因几乎是偶然的,但是它会起作用.

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

你没有"正确"使用它,但它仍然适合你.怎么样?好吧,所有需要发生的事情是需要调用代理上的方法IOngoingStubbing才能when()在执行之前注册.您不是直接在代理上调用方法,而是通过将代理传递给代理来间接调用代理上的方法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!
}
Run Code Online (Sandbox Code Playgroud)

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

虽然Mockito不太可能改变事情的基本方式,但未来某个时候仍有可能为你打破这种局面.就像我说的那样,它或多或少是一个幸运的事故.只要您了解其运作方式和所涉及的风险,您就会获得更多权力.