模拟验证参数顺序

时间:2018-10-11 09:29:41

标签: java testing mockito

我已经搜索了一段时间,没有答案。

让我说我有一个类 Service ,它使用 Calc 依赖项

计算具有方法除法

public void divide(int a,int b)

服务如此使用

public void serviceAMethod{
//do somehting
a=getA();
b=getB();
calc.divide(a,b);
}

我的测试看起来像这样

@Test
public void serviceAMethod_callsCalc(){
   verify(calcMock).divide(a, b);
}

这通过了,但是如果我转到 Calc.divide 并将签名更改为

public void divide(int b,int a)

它仍然通过

如何测试以正确的顺序传递正确的参数?

编辑:不一定非要使用Mockito,如何使此测试更具弹性?

3 个答案:

答案 0 :(得分:2)

这是因为传递给Calc.divide的值仍然相同。 Mockito验证传递的值而不是参数的名称。因此,除非您更改在serviceAMethod方法中所做的调用以反映更改,否则更改Calc类中参数的顺序不会影响测试。

public void serviceAMethod() {
  //do somehting
  a=getA();
  b=getB();
  calc.divide(b,a);
}

只有在更改此逻辑(这就是您要测试的逻辑)之后,测试才会失败。

如果使用实际值,您可以看到以下内容:

public void serviceAMethod() {
   a=getA(); // EG: 1 
   b=getB(); // EG: 2
   calc.divide(1, 2); // effective call
}

如果您在Calc类中交换a和b,则仍将使用值1、2对其进行调用。您将测试以下内容:

verify(calcMock).divide(1, 2);

答案 1 :(得分:0)

在对serviceAMethod进行测试的情况下,假设divide的签名即第一个参数为除数,第二个参数为除数。

现在divide的签名已更改,即第一个参数现在是除数,第二个参数是除数。但是serviceAMethod的测试仍然通过。

用于calc的单元测试肯定会捕获到这一点,但是如果divide的每个客户端的某些测试在这种情况下也失败,则很方便,因为divide的签名更改肯定会破坏客户端,并且要求更改客户。

当您更改方法解释其参数的方式时,肯定需要更改该方法的客户端。测试模拟divide无法检测到这种变化。

使用真实的serviceAMethod的{​​{1}}的集成测试将检测到这种变化并将中​​断。这会提醒您Calc应该更改,以便它以其他顺序传递参数。

答案 2 :(得分:0)

好的,这是我的解决方案,我认为它比全面的集成测试要好

我将参数重构为pojo

public class OperationRequest {
    private int firstOperand;
    private int secondOperand;
    //equals and hashCode, important!
}

然后Calc.divide变为

calc.divide(OperationRequest request);

和断言

verify(calcMock).divide(new OperationRequest(1,2));

如果您交换操作数,此操作现在将失败