Mockito:是否可以将模拟与方法名称结合以在when()调用内创建methodCall? [英] Mockito: is it possible to combine mock with a method name to create a methodCall inside a when() call?

查看:57
本文介绍了Mockito:是否可以将模拟与方法名称结合以在when()调用内创建methodCall?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我关于StackOverflow的第一个问题.我希望能够执行以下操作:

my first question on StackOverflow. I'd like to be able to do something like:

SomeClass模拟=模拟(SomeClass.class);

字符串methodName ="someMethod";OR方法method = ... someMethod ...

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

Both of these things (the mock and the method) would combine to do the following:

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

当然,'null'值将根据我的需要进行相应的更改,但是我正在尝试确定两件事:

Of course, the 'null' value will be changed accordingly for my needs, but I am trying to determine two things:

1)甚至可以在Java中执行类似 this 的操作吗? =将类对象和方法组合到methodCall中.

1) Is it even possible to do something like this in Java? This = combining a class object and a method into a methodCall.

2)我该怎么做?

我对此进行了无休止的研究,但找不到任何东西.问题在于,即使这可以与常规类和常规方法配合使用(someClass和someMethod可以一起执行someClass.someMethod()),请记住,这必须与 mock对象一起使用>可以在when()调用中使用.

I've researched this endlessly and I can't find anything. The problem is that even if this works with a regular class and a regular method (someClass and someMethod would come together to do someClass.someMethod()), keep in mind that this has to work with a mock object for use inside a when() call.

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

ANSWERED: when(method.invoke(mock)).thenReturn("Hello world."); is the correct syntax and reflection indeed does work inside a when() call. Thanks Kevin Welker!

推荐答案

由于您基本上是要我重新发布我的评论(根据您的回答进行修改)作为答案,所以它是:

Since you basically asked me to repost my comment, modified by your response, as an answer, here it is:

尝试使用反射,如下所示:

Try using reflection as in:

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

不过,我不确定这对您的工作方式如何,因为您不能模拟/监视类 Method (这是最终的).Mockito的 when()仅适用于模拟或间谍.如果这确实适合您,您可以发布更多细节吗?

although, I'm not sure how this is working for you, since you cannot mock/spy class Method (it is final). Mockito's when() only works on mocks or spies. If this is really working for you, can you post a little more detail?

如果它不起作用,则可以-正如我在OP中的评论中所建议的-走CGLib路线并绕过Mockito.确实并不像乍看起来那样困难.在我的OSS项目 Funcito (不是一个模拟框架)中,我精简了很多Mockito CGLib代理代码并根据我的需要重写了它.它使您可以更轻松地了解代理类和拦截方法调用的世界.

If it doesn't work, you can -- as I suggested in my comment in the OP -- go the CGLib route and bypass Mockito. It's really not that difficult as it looks at first. In my OSS project Funcito (not a mocking framework), I stripped down a lot of the Mockito CGLib proxying code and rewrote it for my needs. It gives a much simpler view into the world of proxying classes, and intercepting method calls.

对评论的其他回应我知道这对您有什么帮助,但是我不确定您是否真的了解它的工作原理.之所以可能如此,是因为将来对Mockito本身的工作方式进行更改可能会使您的解决方案在将来遭到破坏.从本质上讲,它起作用的原因几乎是偶然的,但是是的,它会起作用.

ADDITIONAL RESPONSE TO COMMENTS I see how this is working for you, but I am not sure you really understand how it is working. The reason this might matter is because future changes to the way Mockito itself works could render your solution broken in the future. In essence, the reason it works is almost accidental, but yes it will work.

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

The way that when() is supposed to work is that what happens in between the parentheses is a method call on a previously created Mockito-generated mock or spy, which is just a fancy proxy of a class, rather than a real instance of the class. The proxies have special logic that intercepts the fake proxied method call and basically add that to a list of registered proxy-method invocations (it is stored in something called an IOngoingStubbing or something like that) for later use. Since Java evaluates parameters before invoking a method, this guarantees that the proxied method call gets registered/remembered before the when() method is actually executed. What the when() does is pops off this IOngoingStubbing, which then becomes the object on which thenReturns() is called.

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

You are not using this "correctly" but it still works for you. How? Well, all that needs to happen is that a method on the proxy needs to be called in order to be registered in a IOngoingStubbing before when() gets executed. You are not directly invoking a method on a proxy, but you are indirectly invoking a method on a proxy by passing the proxy to Method.invoke(). Hence the criteria is satisfied, and when() already has a proxy-method-call registered in an IOngoingStubbing.

您可以在下面的代码中看到相同类型的偶然"幸福,在您意识到Mockito的工作原理之前,这似乎毫无意义:

You can see the same kind of "accidental" happiness in the following code, which appears at first to make no sense until you realize how Mockito works:

@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 语句之前,代理(即,模拟)实例已调用了正确的方法.

The above test actually passes! Even though the argument to when is null, what counts is that the proxy (i.e., mock) instance had the correct method invoked on it prior to the when statement being invoked.

虽然Mockito不太可能改变基本的工作方式,但在将来某个时候仍有可能打破这种情况.就像我说的那样,它起作用多少是一件快乐的事情.只要您了解它的工作方式和所涉及的风险,就会给您带来更大的力量.

While it is unlikely that Mockito will change the basic way things work under the covers, there is still the potential for this to break for you sometime in the future. Like I said, it is more or less a happy accident that it works. As long as you understand the way it works and the risk involved, more power to you.

这篇关于Mockito:是否可以将模拟与方法名称结合以在when()调用内创建methodCall?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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