单元测试方法参数验证最佳实践

时间:2016-07-28 19:35:30

标签: java unit-testing mockito

在单元测试时验证具有复杂参数的方法调用的最佳实践是什么?

说我正在测试这样的函数:

class ClassA {
  ClassB dependency;

  void someFunction(SomeInputForA input) {
    // do some thing
    dependency.anotherFunction(differentInput);
  }
}

我可以考虑使用正确的输入验证someFunction调用anotherFunction的两个选项:

A)在调用另一个函数

的依赖模拟上进行验证
unitUnderTest.dependency = mockClassB;

InputClass expectedDifferentInput = ... ;

verify(mockClassB).anotherFunction(expectedDifferentInput);

B)在anotherFunction的调用上做一个参数捕获者并断言属性

unitUnderTest.dependency = mockClassB;

ArgumentCaptor<InputClass> captor = ArgumentCaptor.for(InputClass.class);

verify(mockClassB).anotherFunction(captor.capture());

InputClass capturedInput = captor.getValue();
assertEquals(value, capturedInput.param1);
// and more asserts afterwards

这里有建议的路径吗?我倾向于使用captor方法,因为它感觉更严格,并且不依赖于对象等于实现正确。

思想?

3 个答案:

答案 0 :(得分:1)

DifferentInput是否已计算输入?

如果是这样,那么你的B)是你输入A的更好的方法,你希望ClassA将它改为expectedDifferentInput并想要验证调用委托类(ClassB)。您正在验证ClassA的输入和委托逻辑的转换。

如果differentInput与输入没有关系,那么你不需要使用captor,因为你只是在检查委托。

ClassA上someFunction的任何公共调用者都不需要知道ClassB,因此可以说A)和B)方法实际上都是white box testing,在这种情况下你也可以使用绑定器无论如何。当您将输入更改为someFunction时,如果输入计算了differentInput,则绑定者还可以帮助您识别边缘情况。

答案 1 :(得分:0)

您总是可以在传递给mockClassB.anotherFunction()的对象上使用匹配器。例如,如果要比较对象上的字段,可以写:

Matcher<YourClass> yourMatcher = Matchers.hasProperty("yourProperty", Matchers.equals(whatever));
verify(mockClassB).anotherFunction(argThat(yourMatcher));

我更喜欢这种方式,因为您可以分享匹配的语法和匹配器的验证,并且您可以组合匹配器的任何组合。您只需要包含最新的mockito和hamcrest库就可以使其工作。

答案 2 :(得分:0)

我已经使用了争吵者,但非常谨慎。您遇到的最大问题是此路由会创建脆弱的单元测试。当他们对一个班级进行一些小改动然后发现自己在调用那些不应该受到影响的课程时遇到单元测试时,没有人会感到高兴。

话虽如此,绝对必须最终确保拨打正确的电话。但是如果你依赖于equals覆盖工作,那么你依赖的是那个有等效方法的类,那么这就是那个类的合同(以及在那个类中测试过的单元)的一部分,这是合理的。

这就是为什么我投票保持简单并只使用验证。同样的事情,但你的单元测试不那么脆弱。