Abhilash Panigrahi
Abhilash Panigrahi

Reputation: 1525

Working of Mockito's verify and argument captor

I'm trying to test the following method

public void saveToMultipleSources(MyObject myObject)
{
    if (myObject.isOfSomeType()) {
        firstDAO.saveObject(myObject);
        myObject.setContent(null);
    }
    secondDAO.saveObject(myObject);
}

The test I wrote was

@Test
public void testSaveFeature()
{
    //initialize all objects
    obj.saveToMultipleSources(myObject); //myObject has a valid content.
    Mockito.verify(firstDAO).saveObject(myObject); 
    myObject.setContent(null);
    Mockito.verify(secondDAO).saveObject(myObject);
}

But on running, I get the error that expected and actual arguments differ for the verify statement of firstDAO. The expected was an object with valid content but actual arguments invoked are with Content set as null. I tried the exact same thing with ArgumentCaptor as well, but got the same results.

Can someone explain why does Mockito behave this way? I tried logging the entire object and can see valid Content being set just before I call the firstDAO.

Also how do I go about testing this?

Upvotes: 0

Views: 1187

Answers (1)

Timothy Truckle
Timothy Truckle

Reputation: 15622

//initialize all objects
obj.saveToMultipleSources(myObject); //myObject has a valid content.
Mockito.verify(firstDAO).saveObject(myObject); 

The problem is that setting the objects content to null is a side effect of your method. In consequence Mockito compares the recorded parameter (having valid content) with the object modified by your method (having content already set to null).

In that case, how can I test this? – Abhilash Panigrahi

In the test Make myObject a Mockito.spy() and prevent the execution of setContent():

@Test
public void testSaveFeature()
{
    //initialize all objects
    MyObject spyOfMyObject = Mockito.spy(myObject);
    doNothing().when(spyOfMyObject).setContent(null); // special null matcher may be needed...

    obj.saveToMultipleSources(spyOfMyObject); 

    Mockito.verify(firstDAO).saveObject(spyOfMyObject); 
    Mockito.verify(spyOfMyObject).setContent(null);
    Mockito.verify(secondDAO).saveObject(spyOfMyObject);
}

But you most likely want to be sure that myObject.setContent(null); is called before econdDAO.saveObject(myObject);`...

@Test
public void testSaveFeature()
{
    //initialize all objects
    MyObject spyOfMyObject = Mockito.spy(myObject);
    doNothing().when(spyOfMyObject).setContent(null);

    obj.saveToMultipleSources(spyOfMyObject); 

    Mockito.verify(firstDAO).saveObject(spyOfMyObject); 
    InOrder inOrder = Mockito.inOrder(spyOfMyObject,secondDAO);
    inOrder.verify(spyOfMyObject).setContent(null);
    inOrder..verify(secondDAO).saveObject(spyOfMyObject);
}

Upvotes: 1

Related Questions