Question

I have a problem with Mockito.

Is it possible to do such a thing:

ClassX x = mock(ClassX.class)
when(x.methodB()).thenReturn("toto");
String result = x.methodA();

I'm working with Mockito 1.7.

I saw there was a "spy" system but they say it's not recommended to use it (why?) on the item we test...

I tried that spy function anyway but i get a strange behaviour.

Check what i want to do:

Real code:

String methodA(String arg) {
    return this.methodB(arg);
}

String methodB(String arg) {
    return "toto";
}

Test code:

@Test
public void testTest() {
    final ClassX x = spy( new ClassX() );
    final String argument = "arg";
    doReturn("good").when(helper).methodB(argument);
    assertTrue(  x.methodB(argument).equals("good") );
    assertTrue(  x.methodA(argument).equals("good") );
}  

As they said i avoided the when thenReturn syntax that could be a problem with a spy (but it doesn't work either anyway)

The strange thing is that: assertTrue( x.methodB(argument).equals("good") ); is OK

Only the second assertTrue( x.methodA(argument).equals("good") ); is not OK

Actually helper.methodA(argument) returns "toto" -> the real result and not the mock result

It isn't possible to tell mockito to return "good" in this case??? It seems when the test class call methodB it's ok, but if a method of the spy calls the methodB it doesn't work anymore...

I don't know what to do... is it such a strange thing to unit-test 2 methods of the same class and make the tests independent from each others so that a famous mock-test framework doesn't implement this basic function? Isn't it what we just call real unit-testing? Don't understand why they say to avoid using spy method on the tested object...

Thanks

Was it helpful?

Solution

The spy is a different object from the spied object. The spy only delegates to the spied object. So when the spied object calls methodB from methodA, it will call it on itself, not on the spy.

OTHER TIPS

UPDATE: I wrote the stuff below, and then moments later discovered .thenCallRealMethod() which allows you to effectively perform partially stubbing. Mockito authors recommend you use refactoring to separate dependencies into different classes; but they do provide the means to partially stub. I have added a test method to demonstrate this approach, and leave my original comments.

ORIGINAL: I really like Mockito, but this is the one place where EasyMock wins out. I have two solutions for you that don't involve Mockito. The first is to override methodB on your testing instance. The other is to partially mock with EasyMock:

import org.junit.Test;
import static org.junit.Assert.*;
import static org.easymock.EasyMock.*;

public class PartialMockTest {

    class ClassX {
        String methodA(String arg) {return methodB(arg);}
        String methodB(String arg) {return "toto";}
    }

    @Test
    public void MockitoOnClassX(){
        ClassX classx = mock(ClassX.class);
        when(classx.methodB("hiyas")).thenReturn("tomtom");
        when(classx.methodA(anyString())).thenCallRealMethod();
        String response = classx.methodA("hiyas");
        assertEquals("tomtom",response);
    }


    @Test
    public void OverrideOnClassX() {
        ClassX classx = new ClassX(){@Override String methodB(String arg){return "tomtom";}};
        String response = classx.methodA("hiyas");
        assertEquals("tomtom",response);
    }

    @Test
    public void PartialMockOnClassX() throws NoSuchMethodException {
        ClassX classx = createMockBuilder(ClassX.class).addMockedMethod("methodB").createMock();
        expect(classx.methodA("hiyas")).andReturn("tomtom");
        replay(classx);
        String response = classx.methodA("hiyas");
        assertEquals("tomtom",response);
    }

}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top