I am trying to mock spring's applicationContext.getBean(String, Class) method in below manner -
when(applicationContext.getBean(Mockito.anyString(), Mockito.eq(SomeClass.class))).thenAnswer(
new Answer<SomeClass>() {
#Override
public SomeClass answer(InvocationOnMock invocation) throws Throwable {
// doing some stuff and returning the object of SomeClass
}
});
The scenario is that, the applicationContext.getBean method will be called a number of times, each time a with different strings but the same class (SomeClass.class).
The problem I am getting here is that the answer is getting invoked for the very first invocation of getBean method. With each subsequent invocation of getBean I am getting below exception -
******org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
2 matchers expected, 1 recorded:
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));******
Any idea, if I am missing something ?
#Kshitij
I have faced same issue in my previous project. I came across this below doc:
http://static.javadoc.io/org.mockito/mockito-core/2.16.0/org/mockito/Mockito.html#resetting_mocks
Under section 17 it is explained how to use reset()
Example: Let's say we have EvenOddService which finds whether number is even or odd then Test case with reset() will look like:
when(evenOddService.isEven(20)).thenReturn(true);
Assert.assertEquals(evenOddController.isEven(20), true);
//allows to reuse the mock
reset(evenOddService);
Assert.assertEquals(evenOddController.isEven(20), true);
Hope this helps :).
When using Mockito, you need to tell him how many times you will call your mock. You need to make as many when calls as you will need. For instance, if you know you'll test your method three times, you need to declare three separate when statements.
PS: I used Mockito for a bit only, it is possible that there is a solution to tell Mockito to use the same Answer multiple times in a row.
EDIT
Olivier Grégoire pointed out in the comments that you can use a single when call, but call thenAnswer multiple times. It is more elegant this way.
I've added this to my test class:
#AfterEach
public void resetMock(){
Mockito.reset(myMockedService);
}
Related
I am trying to mock a static method with parameters like this :
Mockito.when(StaticClass.staticMethod(Mockito.any(A.class),
Mockito.any(B.class), SomeEnum.FOO))
.thenReturn(true);
I have added the following annotations :
#RunWith(PowerMockRunner.class)
#PowerMockRunnerDelegate(Parameterized.class)
#PrepareForTest({StaticClass.class, A.class, B.class})
But Mockito.any always returns null. Why ?
Short answer: Use doReturn().when() instead of when().then()
Long answer can be found over here:
How do Mockito matchers work?
Matchers return dummy values such as zero, empty collections, or null.
Mockito tries to return a safe, appropriate dummy value, like 0 for
anyInt() or any(Integer.class) or an empty List for
anyListOf(String.class). Because of type erasure, though, Mockito
lacks type information to return any value but null for any()
NullPointerException or other exceptions: Calls to
when(foo.bar(any())).thenReturn(baz) will actually call foo.bar(null),
which you might have stubbed to throw an exception when receiving a
null argument. Switching to doReturn(baz).when(foo).bar(any()) skips
the stubbed behavior.
Side Note: This issue could also be described something like, How to use Mockito matchers on methods that have precondition checks for null parameters?
Firstly, you can't mix matchers with actual arguments. You should use a matcher for the SomeEnum argument too:
Mockito.when(StaticClass.staticMethod(Mockito.any(A.class),
Mockito.any(B.class), Mockito.eq(SomeEnum.FOO))
.thenReturn(true);
Secondly, the any() methods should return null. That is exactly what they do. If you look at the code for these methods they return the default value for the class type if it is primitive wrapper object (like Integer, Boolean etc.) otherwise it returns null:
public <T> T returnFor(Class<T> clazz) {
return Primitives.isPrimitiveOrWrapper(clazz) ? Primitives.defaultValueForPrimitiveOrWrapper(clazz) : null;
}
You are getting things wrong. The one and only purpose of matcher methods such as any() is to match the arguments that come in at execution time.
You use these methods to instruct the mocking framework what calls you expect to happen. Or the other way round you use them to say: if this or that is coming in as argument then do this or that.
Therefore you absolutely do not care about the results of matcher invocations.
In that sense your question is indicating that your usage of the mocking framework is going the wrong way. Thus the only answer we can give regarding your current input: A) do some more research how to use mocking and B) then rework your question to be clear about your problem.
It was because it was a Parameterized test, and I did the mockStatic in the #Before method. When I do the mockStatic in the same method, it works.
I need to use a third party class in Mockito.when as parameter. The class does not have equals implementation and hence Mockito.when always returns null except the case where any() is used.
The below always returns null:
when(obj.process(new ThirdParytClass())).thenReturn(someObj);
however, this works
when(obj.process(any(ThirdParytClass.class))).thenReturn(someObj);
But, the problem is the process() method is called twice in the actual code and the use of any() is ambiguous and does not help in covering the multiple scenarios to test.
Extending the class does not help and also leads to other complications.
Is there a way to address the issue.
If a class doesn't implement a (sensible) equals(Object), you can always match instances yourself by implementing your own ArgumentMatcher. Java 8's functional interfaces make this pretty easy to write (not that it was such a big hardship in earlier versions, but still):
when(obj.process(argThat(tpc -> someLogic()))).thenReturn(someObj);
More often than not, however, if you just want to compare the class' data members, the built-in refEq matcher would do the trick:
ThirdParytClass expected = new ThirdParytClass();
// set the expected properties of expected
when(obj.process(refEq(expected))).thenReturn(someObj);
Mockito provides the captor feature that may help you to bypass limitations of equals() method because overriding equals() to make a test pass may be desirable but it is not always the case.
And besides, sometimes, equals() may not be overridable. It is your use case.
Here is a example code with an ArgumentCaptor :
#Mock
MyMockedClass myMock;
#Captor
ArgumentCaptor argCaptor;
#Test
public void yourTest() {
ThirdPartyClass myArgToPass = new ThirdPartyClass();
// call the object under test
...
//
Mockito.verify(myMock).process(argCaptor.capture());
// assert the value of the captor argument is the expected onoe
assertEquals(myArgToPass , argCaptor.getValue());
}
I don't know how can I use Mockito.verify in this case. How can I pass false to Mockito.verify? I try 2 different ways but it does not work.
public Sample someMethod(Sample s, boolean a){....}
#Test
public void test() {
...
verify(mock).someMethod(sampleCaptor.capture(), false));
verify(mock).someMethod(sampleCaptor.capture(), org.mockito.Matchers.eq(false)));
...
}
You have it right the second way:
verify(mock).someMethod(sampleCaptor.capture(), Matchers.eq(false));
When using Matchers (including ArgumentCaptor.capture), you have to use a Matcher for every value, because Matchers work via side-effects.
If the above doesn't work, you may be misusing matchers earlier in the method. It is sometimes helpful to explicitly call Mockito.validateMockitoUsage() immediately before your call to verify, to ensure that there's nothing wrong with Mockito's internal state. (Additional information about how it "does not work", including a minimal reproducible example, may be helpful in solving your specific case.)
I have the following code in a test which uses the Mockito framework to verify that the method drawTextOnCanvas() was called with the correct parameters.
// The two objects below are mocks. The rest of the objects used in
// the call to verify() are plain old java objects I've instantiated elsewhere.
BufferedImage testImage = Mockito.mock(BufferedImage.class);
Mockito.when(testImage.getHeight()).thenReturn(10);
Graphics mockGraphics = Mockito.mock(Graphics.class);
Mockito.when(mockGraphics.getFontMetrics(Matchers.any(Font.class)))
.thenReturn(Mockito.mock(FontMetrics.class));
Mockito.verify(drawingUtil).drawTextOnCanvas(
Matchers.eq(imageCategory.getWidth()),
Matchers.eq(mockGraphics),
Matchers.any(Font.class),
Matchers.eq(Arrays.asList("Test text")),
Matchers.eq(testImage.getHeight() + 10),
Matchers.any(FontMetrics.class),
Matchers.eq(10));
However it throws the following exception:
org.mockito.exceptions.misusing.InvalidUseOfMatchersException:
Invalid use of argument matchers!
0 matchers expected, 4 recorded:
-> at com.test.package(ExampleTest.java:66)
-> at com.test.package(ExampleTest.java:67)
-> at com.test.package(ExampleTest.java:67)
-> at com.test.package(ExampleTest.java:68)
This exception may occur if matchers are combined with raw values:
//incorrect:
someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
//correct:
someMethod(anyObject(), eq("String by matcher"));
For more info see javadoc for Matchers class........
I have however discovered that if I replace the line
Matchers.eq(testImage.getHeight() + 10),
with
Matchers.eq(someInteger),
the test runs with no exceptions, which is what puzzles me.
I've looked at the JavaDoc for Matchers and as far as I can see what I've written should work, unless there is some rule about putting calls to mock objects inside a call to eq() that I've missed.
You've nailed it: You've mocked testImage, and calling a mock method while stubbing is not allowed. The documentation is not clear on that limitation.
I wrote an exhaustive answer on Mockito matchers before (see "implementation details"), but the short version is that Mockito keeps its argument matchers on a stack and that every call to a mocked n-argument method checks that the stack contains exactly 0 or n matchers.
Mockito.verify(drawingUtil).drawTextOnCanvas(
Matchers.eq(imageCategory.getWidth()), // A1
Matchers.eq(mockGraphics), // A2
Matchers.any(Font.class), // A3
Matchers.eq(Arrays.asList("Test text")), // A4
Matchers.eq(testImage.getHeight() + 10), // B
Matchers.any(FontMetrics.class), // C1
Matchers.eq(10)); // C2
The call order is something like this: After verify(drawingUtil), Java prepares the arguments to drawTextOnCanvas in order, calling A1 through A4. Suddenly the call to B happens, and Mockito prepares as if textImage.getHeight() were embedded within a when(...) call. There are 4 matchers on the stack, and Mockito expects either to match by equality (zero matchers) or the number of arguments to getHeight() (also zero matchers). Mockito throws that exception with that "4 matchers recorded" message before even getting to C1, C2, or drawTextOnCanvas.
As a matter of good practice, extract all Matchers.eq values (that contain method calls) to local variables, with a particular emphasis on calls to mocked objects.
The method I want to test is calling a mock method with different arguments:
public void methodToTest(){
getMock().doSomething(1);
getMock().doSomething(2);
getMock().doSomething(3);
}
In my unit test I want to know, if methodToTest really is calling those methods with exactly those arguments. This is the code I wrote:
#Test
public void myMockTest(){
oneOf(mock).doSomething(1);
oneOf(mock).doSomething(2);
oneOf(mock).doSomething(3);
}
At (2) I get an "Unexpected invocation" - as if it couldn't distinguish different arguments. So I've tried that one:
exactly(3).of(mock).doSomething(with(Matchers.anyOf(same(1), same(2), same(3))));
But this also didn't do what I've expected.
Finally, this one worked:
exactly(3).of(mock).doSomething(with(any(Integer.class)));
So I know, that my method was called 3 times with any Integer number. Is there any way to make sure, it's exactly the argument(s) I have passed?
Did you surround the expectations with a checking block?
context.checking(new Expectations() {{
oneOf(mock).doSomething(1);
oneOf(mock).doSomething(2);
oneOf(mock).doSomething(3);
}});
Also, are you aware the jmock does not enforce sequence unless you do so explicitly?