Paul
Paul

Reputation: 419

Understanding what is going on under the hood of Mockito framework

I have a problem understanding what is going on in the Mockito framework here. I have the following classes

Model class

public class KeyValueImpl{

    private String key;
    private String value;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

}

"business logic" class

public class ValueFinder {

    public KeyValueImpl findValueForKey(KeyValueImpl keyValue){
        keyValue.setValue("foo");
        return keyValue;
    }

}

Utility class to return the expected result (will be mocked)

public class ExpectationManager {

    public String getExpectedValue(){
        return "loremipsumdolorem";
    }

}

Test class

public class ValueFinderTest {

    @Test
    public void testMocked() {
        KeyValueImpl keyValue = Mockito.mock(KeyValueImpl.class);
        keyValue = (new ValueFinder()).findValueForKey(keyValue);
        ExpectationManager expectationManager = Mockito.mock(ExpectationManager.class);
        when(expectationManager.getExpectedValue()).thenReturn("somethingDifferentToFoo");
        String expectedValue = expectationManager.getExpectedValue();
        verify(keyValue).setValue(expectedValue);  //fails, expects "foo" but gets "somethingDifferentToFoo" -> ok
        verify(keyValue).setValue(expectationManager.getExpectedValue());  //no error, but why?
    }

}

The interesting thing happens in the last row of the test class:

verify(keyValue).setValue(expectationManager.getExpectedValue());  //no error, but why?

I would certainly expect the same behaviour like in the row above

verify(keyValue).setValue(expectedValue);  //fails, expects "foo" but gets somethingDifferentToFoo" -> ok

However Mockito let's me get along with it. Any explantation for this?

Upvotes: 0

Views: 678

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500055

I suspect the problem is due to the order of the calls. Your last line is effectively:

KeyValueImpl tmp = verify(keyValue);
String value = expectationManager.getExpectedValue();
tmp.setValue(value);

If Mockito is effectively using the verify method call as a marker to say "the next time a mocked method gets called, check it" without validating which mock it's called on, then it'll be the expectationManager.getExpectedValue() call that is verified.

While I would argue this is confusing behaviour in Mockito, I'd also argue that it's a confusing test - using one mock within the verification step of another feels like a design smell to me. I'd strongly consider using manually-written fakes rather than mocks where possible, simply to avoid too much interaction between mocks.

Upvotes: 1

Related Questions