gargPankaj
gargPankaj

Reputation: 27

mock method is not getting called - java

I am new to Mockito, please help in understanding the basic.

According to me above code is supposed to print 5 when mocked.add(6,7) gets called , but add() method is not getting called and the code prints 0.. why ? any solution for this code ?

    import org.mockito.Mockito;

    import static org.mockito.Mockito.*;


    class Calc{

        int add(int a,int b){
        System.out.println("add method called");
        return a+b;
    }

}

      class MockTest{
            public static void main(String[] args) {
            Calc mocked=mock(Calc.class);
            when(mocked.add(2,3)).thenReturn(5);
            System.out.println(mocked.add(6,7));
         }
      }

Upvotes: 1

Views: 4767

Answers (2)

QBrute
QBrute

Reputation: 4537

A "mock" is just an empty dummy object that simulates behaviour of a "real" object. If you define a behaviour such like when(mocked.add(2,3)).thenReturn(5); you specifically tell this mock what to do, when it receives those exact values.

mocked.add(6,7) will return 0 at that point, since you haven't defined its behaviour for those values and therefore uses a default value. So if you want to cover all possible inputs, you can go with the solution @MaciejKowalski posted and use the generic matchers like Mockito.any(Integer.class).

Still I believe it is not clear how to correctly handle mocks. Mocks are a way of providing external dependencies to a system-under-test without the need to set up a whole dependency tree. The real methods inside that class are usually not called. That's what something like when(mocked.add(2,3)).thenReturn(5); means. It tells the mock to behave like the real dependency without actually having it at hand.

An example could look like this:

public class TestClass {
    private ExternalDependency dep;
    public void setDep(ExternalDependency dep) {
        this.dep = dep;
    }
    public int calculate() {
        return 5 + dep.doStuff();
    }
}

public class ExternalDependency {
    public int doStuff() {
        return 3;
    }
}

Now in your test code you can use mocks like this:

@Test
public void should_use_external_dependency() {
    // Aquire a mocked object of the class
    ExternalDependency mockedDep = Mockito.mock(ExternalDependency.class);
    // Define its behaviour
    Mockito.when(mockedDep.doStuff()).thenReturn(20);

    TestClass sut = new TestClass();
    sut.setDep(mockedDep);

    // should return 25, since we've defined the mocks behaviour to return 20
    Assert.assertEquals(25, sut.calculate());
}

If sut.calculate() is invoked, the method in ExternalDependency should not be really called, it delegates to the mocked stub object instead. But if you want to call the real method of the real class, you could use a Spy instead with Mockito.spy(ExternalDependency.class) or you could do that with when(mockedDep.doStuff()).thenCallRealMethod();

Upvotes: 0

Maciej Kowalski
Maciej Kowalski

Reputation: 26492

In order to get result of 5, you have to pass the exact params as when you set up the when..then. Otherwise mockito will return a 'default' value (which is 0 for integer:

What values do mocks return by default?

In order to be transparent and unobtrusive all Mockito mocks by default return 'nice' values. For example: zeros, falseys, empty collections or nulls. Refer to javadocs about stubbing to see exactly what values are returned by default.

If you want to return 5 for any integer then use:

when(mocked.add(Mockito.any(Integer.class),Mockito.any(Integer.class))).thenReturn(5);

Upvotes: 2

Related Questions