使用When来存根返回值的模拟语法



我有一个计算器界面:

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

我也有一个视图接口:

public interface IView {
public void appendAnswer(double anwer);
}
我的控制器类有一个方法:
public void handle(String inputExpression) {
    view.appendAnswer(calculator.evaluate(inputExpression));
} 

我试图创建一个单元测试处理使用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?

我需要测试的是,当void方法句柄接收到字符串时视图。调用appendAnswer时带有相应的双参数。

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

失败,提示"Expected iView.appendAnswer(2.0), actual iView.appendAnswer(0.0)"。试图找到一个答案让我相信我需要一个when子句在我的setup()参数,但我一直搞不懂语法。

你嘲笑了你的计算器

calculator = mock(ICalculator.class);

它的所有方法都将返回一些默认值,大多数引用类型为null,数值类型为0, falseboolean

如果你想让这些方法返回一个预先设定的值,你需要存根它们。你可以用Mockito#when(Object)

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

Xyz取决于你想做什么。在本例中,我假设您想要

calculator.evaluate(inputExpression)

当给定任何String值时,返回2.0的evaluate方法。

你可以用

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

或者,如果您已经知道要传递的String值,则可以直接使用

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

在本例中,您可以验证使用正确的值

调用evaluate
verify(calculator).evaluate(expression);

根据你的评论,你需要一个类似于

Answer
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;
    }
});

首先,应该使用when定义mock的行为:

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

则应调用待测试单元:

controller.handle("2.0");

之后验证mock是否正确调用:

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

(使用了许多来自Mockito的静态导入,顺便说一句:没有使用@Mock注释)

最新更新