Saf
Saf

Reputation: 517

Mockito syntax for using When to stub return values Java Junit

I have a Calculator interface:

public interface ICalculator {
public double evaluate(String expression);
}

I also have a View interface:

public interface IView {
public void appendAnswer(double anwer);
}

My Controller class has a method:

public void handle(String inputExpression) {
    view.appendAnswer(calculator.evaluate(inputExpression));
} 

I'm trying to create a unit test for handle using Mockito.

private Controller controller;

@Mock
ICalculator calculator;
IView view;

@Before
public void setup() { 
    controller = new Controller();
    calculator = mock(ICalculator.class);
    view = mock(IView.class);

    controller.setCalculator(calculator);
    controller.setView(view);

//need a when here?

What I need to test for is that when the void method handle receives a String, the view.appendAnswer is called with a corresponding double argument.

@Test
public void testControllerHandleMethodCallsViewAppendAnswerMethodPassingADouble() {
    controller.handle("2.0");
    verify(view, times(1)).appendAnswer(2.0);
}

Fails with "Expected iView.appendAnswer(2.0), actual iView.appendAnswer(0.0)". Trying to find an answer has led me to believe I need a when clause in my setup() argument, but I've been unable to figure out the syntax.

Upvotes: 1

Views: 7063

Answers (2)

Sotirios Delimanolis
Sotirios Delimanolis

Reputation: 280102

You've mocked your calculator

calculator = mock(ICalculator.class);

All its method will return some default value, null for most reference types, 0 for numerical types, and false for boolean.

If you want these methods to return a pre-set value, you need to stub them. You can do that with Mockito#when(Object).

Mockito.when(calculator.someMethod()).thenXyz()

Xyz depends on what you want to do. In this case, I assume you want

calculator.evaluate(inputExpression)

the evaluate method to return 2.0 when given any String value.

You can do that with

Mockito.when(calculator.evaluate(Mockito.any(String.class))).thenReturn(2.0);

Alternatively, if you already know which String value you will pass, you can use that directly

String expression = ...;
Mockito.when(calculator.evaluate(expression)).thenReturn(2.0);

In this case, you can verify that evaluate was called with the right value

verify(calculator).evaluate(expression);

Based on your comments, you need an Answer more or less like

Mockito.when(calculator.evaluate(Mockito.any(String.class))).thenAnswer(new Answer<Double>() {
    @Override
    public Double answer(InvocationOnMock invocation) throws Throwable {
        String argument = invocation.getArgumentAt(0, String.class);
        Double returnValue = Double.parseDouble(argument);
        return returnValue;
    }
});

Upvotes: 3

Arne Burmeister
Arne Burmeister

Reputation: 20604

First you should define the behavior of your mocks using when:

when(calculator.evaluate(anyString()))
  .thenReturn(2.0);

Then the unit to be tested should be called:

controller.handle("2.0");

Afterwards verify the mocks are called right:

verify(calculator).evaluate(eq("2.0"));
verify(view).appendAnswer(eq(2.0));

(Used many static imports from Mockito, btw: the @Mock annotation is not used)

Upvotes: 2

Related Questions