[FIXED] Mockito ArgumentMatcher saying Arguments are Different

Issue

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());
    } 
}

Solution

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.

Answered By – Morfic

Answer Checked By – Gilberto Lyons (Easybugfix Admin)

Leave a Reply

(*) Required, Your email will not be published