Reputation: 517
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
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
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