I am using Mockito for Unit testing and I am using ArgumentMatcher to check if a particular field of an argument has a particular value.
I have a StatusMatcher class that extends ArgumentMatcher and checks whether an object of class MyClass has a particular value in status field. The way I am invoking this in the tests is:
verify(myDAO, times(1)).update(argThat(new StatusMatcher("SomeStatus")));
Here update
is the method of the DAO that is getting called with some MyClass object. I want to see if it has the correct status or not. This is what I get:
Argument(s) are different! Wanted:
myDAO.update(
<Status matcher>
);
-> at com.foo.bar.MyTest.test1
Actual invocation has different arguments:
myDAO.update(
com.foo.bar.MyClass
);
Note that this is working perfectly for all the test cases except one test case. So I know the StatusMatcher etc. have been coded correctly. I am not sure what is different about the method where its getting this exception.
What I want to know is: under what conditions will the ArgumentMatcher throw such exception so I can find out what I am missing (It is not for me to paste the actual method codes) Please tell me if the explanation is not clear enough, and I will try to improve it. Thanks for reading this far :)
EDIT: Here is the code for my StatusMatcher class
private class StatusMatcher extends ArgumentMatcher<MyClass> {
private String status;
public StatusMatcher(String hs) {
status = hs;
}
@Override
public boolean matches(Object argument) {
return status.equals(((MyClass)argument).getStatus());
}
}
Since Mockito any(Class) and anyInt family matchers perform a type check, thus they won't match null arguments. Instead use the isNull matcher.
Mockito verifies argument values in natural java style: by using an equals() method.
Argument matchers are mainly used for performing flexible verification and stubbing in Mockito. It extends ArgumentMatchers class to access all the matcher functions. Mockito uses equal() as a legacy method for verification and matching of argument values.
By default, Mockito verifies argument values by using the equals() method, which corresponds to == in Kotlin. However, once argument matchers like any() are used, then the eq argument matcher must be used for literal values. In MockK, eq is always used as the default argument matcher.
Like you said, it fails because the arguments are different. Take a look at the test below and you'll see that the second test method will fail because the status in your MyClass
instance is different from SomeStatus
that you passed in the matcher.
public class MatcherTest {
class MyClass{
private String status;
MyClass(String status) {
this.status = status;
}
public String getStatus(){
return status;
}
}
class MyDao {
public void update(MyClass myClass){}
}
class StatusMatcher extends ArgumentMatcher<MyClass> {
private String status;
public StatusMatcher(String hs) {
status = hs;
}
@Override
public boolean matches(Object argument) {
return status.equals(((MyClass)argument).getStatus());
}
}
@Test
public void shouldMatchStatus(){
MyDao mock = mock(MyDao.class);
mock.update(new MyClass("expectedStatus"));
verify(mock, times(1)).update(argThat(new StatusMatcher("expectedStatus")));
}
@Test
public void shouldNotMatchStatus(){
MyDao mock = mock(MyDao.class);
mock.update(new MyClass("unexpectedStatus"));
/* THE BELLOW WILL FAIL BECAUSE ARGUMENTS ARE DIFFERENT */
verify(mock, times(1)).update(argThat(new StatusMatcher("expectedStatus")));
}
}
I could take a wild guess that you could be reusing variables, or have a static field, etc. But without seeing your test code, no one can tell.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With