我是否需要验证与模拟的交互或仅检查方法的输入和输出?

Jin*_*hah 3 unit-testing mocking mockito

是否有必要验证与 Mock 对象的交互?假设我有一堂课:

Class A{
    B b;

    public A(B b){
       this.b = b;
    }

    int getObjectFromDatabase(int id){
       Object o = b.get(id);
       // do some extra work
       return result
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我正在测试该getObjectFromDatabase方法。我已经传递了B类的Mock对象,是否需要验证b.get(id)正在调用的交互?或者只检查我得到的输入和输出结果是一个好主意吗?

Jef*_*ica 5

一般来说,验证存根调用是否发生是没有必要的,并且会导致脆弱的测试(即使实现保持正确,测试也会失败)。get(id)就您而言,是否被调用或被调用多少次可能并不重要;唯一重要的是返回的对象是否正确,并且可能需要b.get(id)在某个时刻调用才能获得正确的结果。

Mockito 在其Javadoc中有一些明确的建议verify(T)

尽管可以验证存根调用,但通常它只是多余的。假设您已经对 foo.bar() 进行了存根操作。如果您的代码关心 foo.bar() 返回什么,那么其他东西就会中断(通常在 verify() 执行之前)。如果您的代码不关心 get(0) 返回什么,那么它不应该被存根。不相信?看这里

verify(b).get(id)尽管在测试缓存或延迟加载行为时,或者在交互是测试行为的关键部分的其他情况下,一定次数(包括零)可能有意义,但应努力测试正确的输出/状态验证您预期的交互