测试模拟对象的良好实践

问题描述

优良作法是广泛匹配模拟对象,但要精确验证它们。 例如:

使用此:

when(myMock.has(any())).thenReturn(myValue);

而不是:

when(myMock.has(eq("blah")).thenReturn(myValue);

伴随:

var result = myMethod();
assertthat(result,is(myValue));

因为它确保始终返回myValue,而不考虑has方法的输入。

对此规则有很好的解释,但我找不到它。 大致如下:match widely and verify precisely

如果您可以向我提供有关规则名称或对该规则的引用的信息,那将是很棒的事情?

解决方法

解释很简单:它将使您的生活更加轻松。

想象一下,调用者不会使用“ blah”调用您的方法的情况。在这种情况下,您依赖于模拟框架将返回什么,很可能为null,零或false。然后,您的测试将朝另一个方向运行,甚至失败,并出现NullpointerException。对于其他开发人员,很难理解这里出了什么问题。

如果广泛匹配,您的测试将按预期进行,但是之后应进行验证,以确保测试无故失败。开发人员往往会省略验证步骤,这会使测试变得非常无用。 通常,没有理由匹配精确的参数值,除非您希望模拟对两个值采取不同的操作。

大多数框架都提供用于方法调用验证的方法,例如Mockito:

@Mock
private Repository repository;

@Test
private void testReadData() {
    Mockito.when(repository.findById(any())).thenReturn(yourEntity);
    
    // run your test
    
    Mockito.verify(repository).findById("foo");
}