my first question on StackOverflow. I’d like to be able to do something like:
SomeClass mock = mock(SomeClass.class);
String methodName = “someMethod”; OR Method method = …someMethod…
Both of these things (the mock and the method) would combine to do the following:
when(mock.someMethod()).thenReturn(null);
Of course, the ‘null’ value will be changed accordingly for my needs, but I am trying to determine two things:
1) Is it even possible to do something like this in Java? This = combining a class object and a method into a methodCall.
2) How do I do such a thing?
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.
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:
although, I’m not sure how this is working for you, since you cannot mock/spy class
Method(it is final). Mockito’swhen()only works on mocks or spies. If this is really working for you, can you post a little more detail?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.
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.
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 anIOngoingStubbingor 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 thewhen()method is actually executed. What thewhen()does is pops off this IOngoingStubbing, which then becomes the object on whichthenReturns()is called.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
IOngoingStubbingbeforewhen()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 toMethod.invoke(). Hence the criteria is satisfied, andwhen()already has a proxy-method-call registered in anIOngoingStubbing.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:
The above test actually passes! Even though the argument to
whenis null, what counts is that the proxy (i.e., mock) instance had the correct method invoked on it prior to thewhenstatement being invoked.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.