Mockito - difference between doReturn() and when() - java

I am currently in the process of using Mockito to mock my service layer objects in a Spring MVC application in which I want to test my Controller methods. However, as I have been reading on the specifics of Mockito, I have found that the methods doReturn(...).when(...) is equivalent to when(...).thenReturn(...). So, my question is what is the point of having two methods that do the same thing or what is the subtle difference between doReturn(...).when(...) and when(...).thenReturn(...)?
Any help would be appreciated.

The two syntaxes for stubbing are roughly equivalent. However, you can always use doReturn/when for stubbing; but there are cases where you can't use when/thenReturn. Stubbing void methods is one such. Others include use with Mockito spies, and stubbing the same method more than once.
One thing that when/thenReturn gives you, that doReturn/when doesn't, is type-checking of the value that you're returning, at compile time. However, I believe this is of almost no value - if you've got the type wrong, you'll find out as soon as you run your test.
I strongly recommend only using doReturn/when. There is no point in learning two syntaxes when one will do.
You may wish to refer to my answer at Forming Mockito "grammars" - a more detailed answer to a very closely related question.

Both approaches behave differently if you use a spied object (annotated with #Spy) instead of a mock (annotated with #Mock):
when(...) thenReturn(...) makes a real method call just before the specified value will be returned. So if the called method throws an Exception you have to deal with it / mock it etc. Of course you still get your result (what you define in thenReturn(...))
doReturn(...) when(...) does not call the method at all.
Example:
public class MyClass {
protected String methodToBeTested() {
return anotherMethodInClass();
}
protected String anotherMethodInClass() {
throw new NullPointerException();
}
}
Test:
#Spy
private MyClass myClass;
// ...
// would work fine
doReturn("test").when(myClass).anotherMethodInClass();
// would throw a NullPointerException
when(myClass.anotherMethodInClass()).thenReturn("test");

The Mockito javadoc seems to tell why use doReturn() instead of when()
Use doReturn() in those rare occasions when you cannot use Mockito.when(Object).
Beware that Mockito.when(Object) is always recommended for stubbing
because it is argument type-safe and more readable (especially when
stubbing consecutive calls).
Here are those rare occasions when doReturn() comes handy:
1. When spying real objects and calling real methods on a spy brings side
effects
List list = new LinkedList(); List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws
IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing:
doReturn("foo").when(spy).get(0);
2. Overriding a previous exception-stubbing:
when(mock.foo()).thenThrow(new RuntimeException());
//Impossible: the exception-stubbed foo() method is called so
RuntimeException is thrown. when(mock.foo()).thenReturn("bar");
//You have to use doReturn() for stubbing:
doReturn("bar").when(mock).foo(); Above scenarios shows a tradeoff
of Mockito's elegant syntax. Note that the scenarios are very rare,
though. Spying should be sporadic and overriding exception-stubbing is
very rare. Not to mention that in general overridding stubbing is a
potential code smell that points out too much stubbing.

Continuing this answer, There is another difference that if you want your method to return different values for example when it is first time called, second time called etc then you can pass values so for example...
PowerMockito.doReturn(false, false, true).when(SomeClass.class, "SomeMethod", Matchers.any(SomeClass.class));
So it will return false when the method is called in same test case and then it will return false again and lastly true.

The latter alternative is used for methods on mocks that return void.
Please have a look, for example, here:
How to make mock to void methods with mockito

Related

Compare Mockito enhanced classes against their regular counterparts

I've created a simple test class with two fields like
#Mock
private MyTestClass myTestClass;
#Spy
private final MyContext context = CommonTestData.getDefaultContext();
Basically I don't really need the spy functionality here, it is just used to automatically inject the object into other mocks.
For the test, I tried to configure myTestClass like this:
when(myTestClass.someMethod(eq(context))).thenReturn(someValue);
The problem now is, that Matchers.eq is not matching "un-enhanced" versions of MyContext. So when someMethod is called during the test with a "regular" instance of MyContext that actually equals the value used for context, the stubbed method is not called.
It seems like the Mockito enhanced MyContext class implements its own equals method, at least the equals method of MyContext never seems to be called. Thus, I currently can't think of any way to modify the actual comparison being done.
I can think of various workarounds for this issue like using a custom argument matcher or stubbing the method with an instance of the "real" object. I was however wondering: Is there any Mockito-provided solution to check for equality of enhanced classes against their regular counterparts?
This is conceptually wrong: the idea of equals() in Java is to be symmetric: when a.equals(b) then you better find that b.equals(a), too!
And in your case, a has class MyContext, and b has WhateverMockitoSpyDoesToMyContext. So even when the equals() of the mockito generated thing works, most likely the other way round, that "base" equals might return false (because the original MyContext class knows nothing about potential subclasses like what Mockito is doing here).
I agree that it might be convenient to have your example work out, but I am simply not aware of a "correct" way getting there. From that point of view, you actually have to look into use an ArgumentMatcher.
Beyond that: seriously consider if you really gain anything by using eq() in the first place. If that check is the "core" of your test, then sure, somehow you better look for clear ways to have that check. But if it is more of a byproduct: then just use any() instead.
Meaning: don't make your tests more complicated than necessary. Normally, you setup things for one specific case anyway. You only have to worry about things passed to someMethod() if your code under test could actually, correctly pass different objects to that method.

How do I get Mockito mocks to cause a failure when unexpected calls are made?

I have some mock objects that are probably going to get passed around a bit and might end up being fairly complex.
I'd like to either have Mockito output a log for each call made to a mock or I'd like it to fail whenever an unexpected call is made so I can iterate through those calls and set up appropriate responses.
How can I accomplish this?
The most-idiomatic way of doing this is with verifyNoMoreInteractions, as in Mockito docs #8:
//interactions
mock.doSomething();
mock.doSomethingUnexpected();
//verification
verify(mock).doSomething();
//following will fail because 'doSomethingUnexpected()' is unexpected
verifyNoMoreInteractions(mock);
I say "most-idiomatic" above because that method has its own warning label, which links to the blog post "Should I worry about the unexpected?" by Mockito originator Szczepan Faber.
verifyNoMoreInteractions() is not recommended to use in every test method. verifyNoMoreInteractions() is a handy assertion from the interaction testing toolkit. Use it only when it's relevant. Abusing it leads to overspecified, less maintainable tests.
In short, you should have a very clear reason to check what your dependency is not doing or what your system-under-test is not calling, as opposed to what they are doing and calling. You might use verifyNoMoreInteractions for an RPC object, if you want to avoid unnecessary RPC calls, but not (say) a calculator with no side effects. Even better is to specify your exact requirements with never() or times(int) as parameters to verify.
That said, there are two even-less-idiomatic ways of doing this:
You can take an overall log of calls made using mockingDetails(Object) and iterating through getInvocations(). That should reflectively give you a whole list of the invocations. I have a hard time imagining how this would be useful in a test, but it might be useful in cleaning up a nebulous or poorly-documented existing system.
You can make the mock's default action to throw an exception, which means that if anyone calls something that you haven't stubbed, the test will immediately fail.
// untested pseudocode
YourObject yourObject = Mockito.mock(YourObject.class, withSettings()
.defaultAnswer(invocation -> {
throw new UnsupportedOperationException(invocation.toString());
}));
Sure, that'd work, but you'd not only be violating one of Mockito's core principles (mocks are nice by default, using EasyMock's definition of "nice"), but you'd also force yourself to only stub using doVerb (doReturn, doAnswer, etc) because calls to when(yourObject.doAnything()) would necessarily throw that exception before the call to when would even run.
Developers who are familiar with Mockito would likely say that this exception-prone cure is worse than the disease, and may be useful only for temporarily diagnosing the most tangled legacy code.
I was just asking myself the same question and... The solution using ReturnsSmartNulls will return SmartNulls instead of null... So it is meaningful for non-void methods only right ? What about void methods, the ones having side effects ?
In my opinion, if you want to make sure that your test fails when a method of your mock is called without your explicit behavior definition of it (doXXX(...).when(...) mockito methods) you can initialize your mocks with a custom default answer that will throw an exception, or better... fail your test.
For example you can add the following class inside your test class (or outside if you intend to use it elsewhere, or even use a MockitoConfiguration class as previously mentionned depending on what you want):
static class FailAnswer implements Answer<Object> {
#Override
public Object answer(InvocationOnMock invocation) {
String methodName = invocation.getMethod().getName();
String className = invocation.getMethod().getDeclaringClass().getSimpleName();
return fail(String.format("%s#%s should not have been called", className, methodName));
}
}
Then init your mock with this fake answer in your setUp method :
#BeforeEach
void setUp() {
delegateService = mock(DelegateService.class, new FailAnswer());
classUnderTest = new ClassUnderTest(delegateService);
}
Unfortunately, this solution is not compatible with #Mock annotation which only takes native predefined answers from org.mockito.Answers enum as argument. So that forces you to manually init every mock, spy, captor within the setUp method (RIP MockitoAnnotations.initMocks(this))
Benefit :
you get rid of default behavior of mockito mocks, sometimes hidding unintentionnal uses of mocks for specifics use cases (does is really matter ?)
=> You must define everything you use (inside tests or tests fixtures)
=> you don't have to make verification to make sure your test have not invoked methods it shouldn't have.
Drawbacks :
This is an unusual usage of mockito, so this makes your test less affordable
You give up on MockitoAnnotations feature
As you override mockito default stubbing, you must use the stubbing form do().when() instead of when(...).do(....), the latter providing au type-checking unlike the former.
Warning : This solution doesn't garantee your mock is called, it just garantees that the method you don't stub won't be called. It doesn't come as replacement for counting methods invocations neither.
The best answer I found is to configure Mockito to return SmartNulls.
https://static.javadoc.io/org.mockito/mockito-core/2.6.9/org/mockito/Mockito.html#RETURNS_SMART_NULLS
This implementation can be helpful when working with legacy code. Unstubbed methods often return null. If your code uses the object returned by an unstubbed call you get a NullPointerException. This implementation of Answer returns SmartNull instead of null. SmartNull gives nicer exception message than NPE because it points out the line where unstubbed method was called. You just click on the stack trace.
You can do it by mock or by default (might cause problems with other frameworks like Spring).
Manually
Writer writerMock = mock(Writer.class, RETURNS_SMART_NULLS);
Annotation
#Mock(answer = Answers.RETURNS_SMART_NULLS)
Set as Global Default
Configuration class must be in exactly this package. This might lead to strange failures with Spring.
package org.mockito.configuration;
import org.mockito.internal.stubbing.defaultanswers.ReturnsSmartNulls;
import org.mockito.stubbing.Answer;
public class MockitoConfiguration extends DefaultMockitoConfiguration {
public Answer<Object> getDefaultAnswer() {
return new ReturnsSmartNulls();
}
}
See: https://solidsoft.wordpress.com/2012/07/02/beyond-the-mockito-refcard-part-1-a-better-error-message-on-npe-with-globally-configured-smartnull/
I had problems with SpringBootRepositories and #MockBean when enabling the global default:
java.lang.ClassCastException: org.mockito.codegen.Object$MockitoMock$191495750 cannot be cast to xxx.xxx.MyObject
Example of error output
org.junit.ComparisonFailure: expected:<[DataRecordType{id=null, name='SomeRecord', pathTemplate='SomeTemplate'}]> but was:<[SmartNull returned by this unstubbed method call on a mock: dataRecordTypeRepository bean.getById(1L);]>
If you are trying to track the flow, you can use Mockito verify to check if certain call has been made.
verify(yourMockedObject).yourMethod();
you can also use times to verify if certain call has to be made exactly some number of times.
verify(yourMockedObject, times(4)).yourMethod();
It is not a good practice to make your unit test complex. Try to test only small unit of your code at a time.

Unit testing method parameter verification best practice

What is the best practice for verifying a method call with complex parameters when unit testing?
Say I'm testing a function like this:
class ClassA {
ClassB dependency;
void someFunction(SomeInputForA input) {
// do some thing
dependency.anotherFunction(differentInput);
}
}
The two options that I can think of for verifying that someFunction calls anotherFunction with the proper input are:
A) do a verify on the mock of dependency for calling anotherFunction
unitUnderTest.dependency = mockClassB;
InputClass expectedDifferentInput = ... ;
verify(mockClassB).anotherFunction(expectedDifferentInput);
B) do an argument captor on the call of anotherFunction and assert the properties
unitUnderTest.dependency = mockClassB;
ArgumentCaptor<InputClass> captor = ArgumentCaptor.for(InputClass.class);
verify(mockClassB).anotherFunction(captor.capture());
InputClass capturedInput = captor.getValue();
assertEquals(value, capturedInput.param1);
// and more asserts afterwards
Is there a suggested path here? I'd lean towards the captor method because it feels more rigorous and is not relying on objects equals implementations being proper.
Thoughts?
Is differentInput computated off input?
If so then your B) is the better way to go as you are saying for Input A, you expect ClassA to change this to expectedDifferentInput and want to verify the delegating class (ClassB) is called. You are verifying the transformation of the input and delegating logic of ClassA.
If differentInput has no relation to input then you don't need to use the captor as really you are just checking delegation.
Any public caller to someFunction on ClassA shouldn't need to know about ClassB so it can be said both methods A) and B) are actually white box testing, in this case and so you might as well use the captors anyway. As you vary your input to someFunction, captors may also help you to identify edge cases if differentInput is computed off input.
You can always use matchers on the object passed into mockClassB.anotherFunction(). For example, if you want to compare fields on an object, you can write:
Matcher<YourClass> yourMatcher = Matchers.hasProperty("yourProperty", Matchers.equals(whatever));
verify(mockClassB).anotherFunction(argThat(yourMatcher));
I prefer this way, since you can share syntax for the when and the verify for the matchers and you can combine any combination of matchers. You just need to include the latest mockito and hamcrest libraries to get this to work.
I've used argument captors but VERY sparingly. The biggest issue you run into is that this route creates fragile unit tests. And no one is happy when they make a small change to a class and then find themselves struggling with unit tests in calling classes that shouldn't have been affected.
That being said, absolutely you have to eventually ensure that correct calls are made. But if you rely on an equals override working, then you are relying on that class having an equals method that works, and this is then part of that class's contract (and unit tested in that class) which is reasonable.
So that's why I'd vote for keeping it simple and just using verify. Same thing in the end, but your unit test is just less fragile.

mockito : mock method call with parameters by reflection

I'm using mockito and developping with java6 and spring.
I'm working on a test API for some developpers and I propose a few methods for mocking objects and methods (it's a legacy code...).
Now, I want to replace all this things by mockito but I always propose a test API. So, I developped some methods using mockito.
I have an old method with two parameters (String). A first parameter is a mocked service id and its method with parameters. And the second parameter is the returned Object.
Example :
mockReturnObject("myServiceId.myMethod(String, Integer)", myReturnedObject);
Now, I want to use mock, when and thenReturn mockito methods, and I don't see how...
Perhaps with reflection but with "when" method it's impossible because mockito need the effective method.
How can I do that ? thanks.
This is a bad idea: you're trying to reimplement some of the systems Mockito already provides while losing out on many of the features Mockito offers. However, there is a way to make this work, with some difficulty. The key is to write a custom Answer, make it the default answer for the mock, and then compare your object, method name, and method parameter types using InvocationOnMock.
public class ReflectiveMockAnswer implements Answer<Object> {
#Override public Object answer(InvocationOnMock invocation) {
// Assume you've successfully parsed each String into a StubbedResponse, with
// Object target, String method, String[] argTypes, and Object returnValue.
// A Set would beat a for-loop here, should you need to optimize.
for (StubbedResponse stubbedResponse : allStubbedResponses) {
if (stubbedResponse.target == invocation.getMock()
&& stubbedResponse.method.equals(invocation.getMethod().getName())
&& stringArraysEqual(stubbedResponse.argTypes,
typeNamesFrom(invocation.getMethod().getParameterTypes())) {
return stubbedResponse.returnValue;
}
}
throw new RuntimeException("Unstubbed method called.");
}
}
// Later...
Object yourMockObject = Mockito.mock(classToMock, new ReflectiveMockAnswer());
At that point, you've implemented a simplified version of Mockito within and based on the full version of Mockito. You'll also need to:
Parse the string into a StubbedResponse, probably with regular expressions
Identify the field in your bean-under-test by name
Replace that field with a mock of the appropriate class, created as above, before the bean-under-test has a chance to interact with it
...and acknowledge that this solution doesn't handle:
Verification
Any sort of argument matching, including basic "equals" matching
Name collisions in parameter types (com.foo.SomeClass vs com.bar.SomeClass)
Repeated calls (thenReturn(1, 2, 3).thenThrow(new RuntimeException()))
...and cannot handle:
Code search tools: you can only tell which methods are mocked other than by searching for strings, not with tools like "Find references" in Eclipse the way Mockito can
Compile-time checking and automated refactoring tools: your tests would break at runtime if field names, method names, or parameters change; Mockito doesn't have that problem
Final methods: Mockito can't, so you can't either
Unless this is a "straw man" or very temporary solution, I recommend strongly to just introduce Mockito directly into your test cases, one test at a time.

Mockito: is it possible to combine mock with a method name to create a methodCall inside a when() call?

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:
when(method.invoke(mock)).thenReturn("Hello world.");
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?
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 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.
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.
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!
}
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.
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.
I think, adding a new method after class initialization is not possible as long as the method is not specified in the interface or class provided to Mockito. You would change the class signature after initialization and this is something which is not possible.
For stub method calls have a look to: http://code.google.com/p/mockito/. There is a sample on stub method calls.
If you want to get dynamic answers, not static ones, you should not use Mockito. Use a fake object or a stub to get you behavior for testing. See: http://martinfowler.com/articles/mocksArentStubs.html for details on this issue.

Categories

Resources