Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mockito ArgumentMatcher saying Arguments are Different

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());
    } 
}
like image 231
Mustafa Hussain Avatar asked Apr 08 '14 09:04

Mustafa Hussain


People also ask

What can I use instead of Mockito matchers?

Since Mockito any(Class) and anyInt family matchers perform a type check, thus they won't match null arguments. Instead use the isNull matcher.

Does Mockito verify use equals?

Mockito verifies argument values in natural java style: by using an equals() method.

What is argument matcher in Mockito?

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.

What does Mockito EQ do?

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.


1 Answers

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.

like image 60
Morfic Avatar answered Oct 19 '22 05:10

Morfic