We try to verify the behaviour of an action with Mockito. The test code looks like this
final Type1 mock = mock(Type1.class);
new SomeAction<Type1>(mock).actionPerformed(null);
verify(mock).someMethod();
The method actionPerformed contains just the call of someMethod on the object provided in the constructor of Type1. Yet Mockito complains that the expected method call did not happen, instead a different method call happened. But the String representation of the two calls printed by Mockito are exactly the same!
Any explanation what is going on?
Update: ErrorMessage from Mockito
Argument(s) are different! Wanted:
type1.someMethod();
-> at xxx
Actual invocation has different arguments:
type1.someMethod();
-> at xxx
This is a bit of a stretch, but check your toString implementations. I've ran into some irritating unit test scenarios where the expected and observed appeared to be the same from the unit test point of view when in reality they were different. In the end it was a variation in toString that caused me to believe there was a similarity when in reality there was not.
Related
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.
I am currently using EasyMock and trying a lot to fix my problem.
Let me explain you in the simple words, Totally I have 5 classes.
Main.java
A.java
B.java
C.java
Result.java
From Main.java I am calling a method of A.java
objectOfA.someMethod("String",objectofB, C.class);
While Mocking...
expect( objectofA.someMethod( "given some String", Prepared some dummy object of B and passing , C.class ) ).andReturn( objectofResult ).anyTimes();
While I am running the application its giving AssersionError.
My Questions:
In the expect method > while calling objectofA.someMethod(), In the second parameter I am creating one dummy object of B, actually B has nearly 10 variables and among them one will be generated randomly, but while creating the dummy object I am giving some value of my own, will it be a problem ?
3rd parameter, we have to pass C.class, How can we pass this ?
Finally in andReturn() I am passing objectofResult class, do I need to parpare the dummy object of Result in this case ? because in Result.java we have nearly 20 variables and its really difficult for me to guess the values.
In Result.java I just need to verify a single String variable value.
I am trying a lot since 3 days, can someone help me to fix this please.
We can't tell you what is "right" for your code; because we don't have the full picture (and you should not expect that somebody will spent his time to dive into all your code if you would have posted it).
So, for your questions:
1) +2) I think you are getting it backward. The point is: you tell EasyMock about the invocations that your "code under test" should make.
This means: you tell EasyMock that someMethod should be invoked; and EasyMock will check if the actual invocation matches your specification.
So, it really depends on your implementation of your B class. If the B object that your actual code passes with someMethod() is equal to the B object that you provide in the EasyMock staging; than all is fine. But if they are not equal, then EasyMock will complain. You can change that for example by using matchers, like
EasyMock.expect(
yourMock.someMethod(
eq("string to match"), anyObject(B.class), ...)
(where eq, anyObject being static methods in EasyMock).
But the problem there is: if you use matchers; you have to use matchers on all your arguments. And (for the moment); I am not aware of a matcher that would work for the "class" argument. So, for now I can only advise to do something like:
EasyMock.expect(
yourMock.someMethod("string to match", expectedB, C.class))
where "expectedB" is a B object that you setup in advance; so that it matches what is created by your code under test. In order to get there, you will have to make sure that your B class as a "good" equals() method.
3) Again; the question what your "dummy result" is capable of; depends on how your code under test will be using it.
Example: assume that your code under test will invoke .toString() on that result object. Then you might want to prepare for that; for example by making that result object ... be another mock; that expects calls to toString().
Long story short: you use EasyMock to specify everything that you expect to "come out" of your class under test; and to control everything that "flows into" that class under test.
I'm new to JMockit and writing a test for a quite complex class, call it XYZ. In each #Test method, I want to call the corresponding real method of XYZ, but mock all (or sometimes nearly all) other methods, which should by verified afterwards. At the moment my first test method looks like this (I want to mock all methods except "start", so I'm using a regex):
#Test
public void testStart(#Mocked({ "^(start).*" }) XYZ xyz) {
new Expectations() {{
xyz.isValidState(); result = true;
}};
...
}
When I run the test, I get "java.lang.IllegalStateException: Missing invocation to mocked type at this point; please make sure such invocations appear only after the declaration of a suitable mock field or parameter" (at the line where the first expectation is defined) which seems to say that the mocking did not work. Is my regex wrong or this there another problem?
That regex selects the methods that will be mocked. So, isValidState() does not get mocked, as it doesn't match the expression; hence JMockit says there was no mocked invocation at the point the "result" field is used.
There is no way to not mock just a single method in a class while mocking all others, except for using partial mocking with new Expectations(XYZ.class) and then recording expectations on all the methods that should be mocked. This, of course, would be cumbersome. Which is a good thing here, because partial mocking in general is not a feature to be used in "normal" cases; it's only for exceptional situations.
If you want to unit test a class, even a complex one, mocking should be restricted to its dependencies, and even then only those dependencies that you choose or need to regard as external to the unit under test. That said, if a given internally called method in XYZ gets in the way of a clean test, then you can exceptionally choose to "mock it out" through partial mocking; but that would usually mean a single method (or just a few) in class XYZ to be mocked per test.
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
I have such method:
<T extends Entity> boolean putObject(T value);
But can`t find out how to mock it using mockito? anyObject() and any() produce error:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
1 matchers expected, 3 recorded.
Mock:
when(service.putObject(any(ProcessingTransaction.class))).thenReturn(true);
How it shold work?
Most likely, you have one or two improperly-formed calls to Mockito methods, somewhere earlier in your test (or even in a previous test). When you call a Mockito method that makes an argument matcher (like any()), the matcher gets added to an internal data structure. It's then removed when it's actually used.
The fact that Mockito found three argument matchers instead of just one suggests that you made some argument matchers but didn't use them. For example, if you use when(...) without thenReturn(), this can happen; but there are lots of other cases too.
If you want help finding exactly what you've done wrong, you need to post more of your test code.