I'm just wondering if it is possible using Junit and easymock to ignore unexpected method calls?
I.e. instead of the test failing I want to be able to say - "at this point - ignore any unexpected method calls and just continue with the test as normal'
Thanks
With EasyMock you can create a nice mock, which unlike a normal mock object does not throw assertion errors if an unexpected/recorded call occurs. To quote the easymock documentation...
On a Mock Object returned by createMock() the default behavior for all methods is to throw an AssertionError for all unexpected method calls. If you would like a "nice" Mock Object that by default allows all method calls and returns appropriate empty values (0, null or false), use createNiceMock() instead.
To create a nice mock, use the static createNiceMock(Class class) method on the Easymock class...
SomeClass someClassNiceMock = EasyMock.createNiceMock(SomeClass.class);
Reference: http://easymock.org/user-guide.html#mocking-nice
Related
I am curious if when(mock.method(SPECIFIC_PARAM)).thenReturn(RETURN_VAlUE); checks for invocation of method. Or should I do verify(mock).method(SPECIFIC_PARAM); to make sure the method has been invoked?
If you use #RunWith(MockitoJUnitRunner.class) or #ExtendWith(MockitoExtension.class), you will get an UnnecessaryStubbingException after running a test if you provided a mock that is not used.
You can avoid this by setting #MockitoSettings(strictness = Strictness.LENIENT) if you want to.
But even with the UnnecessaryStubbingException, it's still better to do an actual verify inside your test for readability. Your 'verify' can also be stricter than your stub, e.g:
when(mock.method(anyCollection())).thenReturn(...)
...
mock.method(collection);
...
verify(mock).method(argThat(collection -> collection.size()==1));
Basically when(mock.method(SPECIFIC_PARAM)).thenReturn(RETURN_VAlUE); signifies that when the method is invoked on the mock then the specified value is returned. The whenis used to configure the mocking, so it doesn't perform any verifications. It is the verify that checks if a method is called.
With the method when(..).thenReturn(...) you are defining a rule on the mock object, in your particular case, you are instructing the mock object to return "RETURN_VALUE" when the method mock.method is invoked with input parameter "SPECIFIC_PARAM".
You are actually not asserting anything over the mock object.
Instead, you can check the effective invocation of the mock's method, by using verify(mock), as you did in your description.
For example, this is what you should expect when your method is not invoked:
got: <Wanted but not invoked: mock.method(SPECIFIC_PARAM);
I have a method inside my service which throws exception for one method call. For example, I have a code like:
void myServiceMethod() {
method1(); // passes
method2(); // passes
method3(); // throws exception
method4(); // passes
method5(); // passes
}
What I want, is to handle this method3 (in real program it is a static method), in some way, so that a program can continue executing further code such as method4 and method5 in this example.
Is it possible in mockito junit test, to return any value instead of exception, or to just skip it?
Your question is actually two:
1: how do I avoid execution the mocked method ?
2: how do I mock static methods?
Here are the answeres:
Mockito provides 2 APIs to configure your mock. The more common (and more readable) for is:
when( mock.mockedMethod() ) .thenReturn(someValue);
The problem her is that the real method is actually executed and just the result is replaced. Usually this is not a problem unless your method throws an (unchecked) exception based on the return values of other (mocked but possibly unconfigured) methods in the same object or tries to access methods on dependencies of the mocked object since they are null so that a NPE is thrown.
One way is to also configure return values for all the other methods in your mocked class. But then you have to "open" your mocked classes API bye raising the visibility of all methods involved above private just for testing. But making such changes just for testing is bad design.
To avoid that you need to use the other form which does not execute the configured method:
doReturn(someValue).when( mock ). mockedMethod();
please mind that the closing brace moved from behind the method call to before the dot separating the mock variable from the method call...
This might also solve your problem with the static method in your dependency in your concrete example.
You stated that the method you want to mock is static in your production code.
The problem here is that you should not use static access in your code in the first place. So the best way is to change your method to an instance method and provide is instance of the class providing your "serviceMethod". Then you can use plain Mockito to create a mock and replace it for testing easily.
Some may argue you can use PowerMock to mock static and/or private methods. While this is technically true I'd consider it a surrender to your bad design...
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.
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
In the following example
when(myMethod("abc", 123)).thenReturn(456);
How does the when() method catch the method name and arguments without actually invoking myMethod()?
Can I write a method to do the same thing as when() so that I get a method pointer and an array of Objects as arguments to invoke later?
The method myMethod is invoked. But it is being invoked on a mock object -- that's the "trick".
Of course you can write code that accepts a "method pointer" (in Java, it would be an object of class Method) and some arguments, and use invoke, but doing so does not actually buy you anything over calling the mock object's myMethod directly.
It is more common to see when called as follows:
MyObject myObject = mock(MyObject.class);
when(myObject.myMethod("abc", 123)).thenReturn(456);
Try printing (or logging) the expression
myObject.getClass().getName()
here. You will see that the class of the mock object is not actually MyObject. But it is of a class that has the same interface. The calls on this object update some internal state. This allows Mockito to keep track of how it is used, and allows you to assert various things.
In your above example, myMethod is a method on a mock object. Without any expectations, Mockito will return null, 0, or false depending on the data type, which when will silently discard.
However, You may also use when on an object which is not a mock, but rather an object created using Mockito.spy(). In this case, the method would actually be called in the when method, which is often not what you want to do. Mockito provides another method called doReturn (or possibly doAnswer or doThrow) which provides you a replacement object so the original is never called (docs):
doReturn(1).when(mySpiedObject).getSomeInteger(anyString(), eq("seven"));
Note that the Mockito docs recommend using when rather than doReturn because the latter is not type-safe.