Java 使用verifyNoMoreInteractions()强制未来测试更新的有效性

Java 使用verifyNoMoreInteractions()强制未来测试更新的有效性,java,unit-testing,junit,mockito,Java,Unit Testing,Junit,Mockito,我的一位同事在JUnit测试中使用Mockito.verifyNoMoreInteractions()来确保将来可能对测试代码进行的更改会导致测试失败,并迫使未来的开发人员在更改测试代码时更新测试 伪代码示例: class TestedClass { DependencyA dependency1; DependencyB dependency2; DependencyC dependency3; public void testedMethod(SomeClass a) {

我的一位同事在JUnit测试中使用Mockito.verifyNoMoreInteractions()来确保将来可能对测试代码进行的更改会导致测试失败,并迫使未来的开发人员在更改测试代码时更新测试

伪代码示例:

class TestedClass {
  DependencyA dependency1;
  DependencyB dependency2;
  DependencyC dependency3;

  public void testedMethod(SomeClass a) {
    if(a == null) {
        return;
    }

    //in real code there are over a dozen of such calls, example code 
    //is simplified for clarity
    dependency1.doA();
    dependency2.doB();
    dependency3.doC();
    //future developer might add dependency3.doOtherC(); here
  }
}

class TestedClassTest {
    @Mock DependencyA dependencyAMock;
    @Mock DependencyB dependencyBMock;
    @Mock DependencyC dependencyCMock;
    @Mock SomeObject someObejctMock;

    TestedClass testedObject;

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        testedObject = new TestedObject(dependencyAMock, dependencyBMock, dependencyCMock);
    }

    @Test
    public void shouldCallDependencyMethods_OnTestedMethod_GivenSomeClassNotNull() {
        testedObject.testedMethod(someObjectMock);

        then(dependencyAMock).should().doA();
        then(dependencyBMock).should().doB();
        then(dependencyCMock).should().doC();

        //is this check acceptable ?
        Mockito.verifyNoMoreInteractions(dependencyAMock, dependencyBMock, dependencyCMock);
    }
}
Mockito文档警告不要这样做():

我们谈到了这一点,他认为,如果测试代码将来发生更改(在示例代码中添加新的依赖方法调用,如dependency3.doOtherC(),理论上可能会发生,但不一定会发生),引入此类更改的开发人员可能不会记得使用相关检查更新测试(在我们的项目中确实发生过几次)。通过使用verifyNoMoreInteractions()检测此类新更改而导致测试失败,也将迫使他们更新测试

因为我的任务是代码审查,所以我必须对这种解决方案采取立场。尽管Mockito文档显然反对这种做法,但我必须承认,在这种特定情况下,我看到了这种“防御性”验证的目的

在这种情况下,这样的解决方案可以接受吗?是否有其他方法可以确保测试得到更新?

  • TestedClass testedObject;
    应使用
    @InjectMock
    注释,并命名为
    cut
    (类卸载测试)
  • 您可以使用
    verifyNoMoreInteractions()
    这就像所有的“扩展”方法一样,如果可能的话,你应该避免
    如果一个函数不使用它的类的任何依赖项,你不需要调用
    verifyNo..
    ——但是如果你不确定这是否会永远这样说,你可以这样做
使用或不使用:就像宗教或政治一样,每个人都可以随心所欲地使用它(使用起来安全,但经常超载)

  • TestedClass testedObject;
    应使用
    @InjectMock
    注释,并命名为
    cut
    (类卸载测试)
  • 您可以使用
    verifyNoMoreInteractions()
    这就像所有的“扩展”方法一样,如果可能的话,你应该避免
    如果一个函数不使用它的类的任何依赖项,你不需要调用
    verifyNo..
    ——但是如果你不确定这是否会永远这样说,你可以这样做
使用或不使用:就像宗教或政治一样,每个人都按照自己的意愿去做(使用安全,但经常超载)

A word of warning: Some users who did a lot of classic, expect-run-verify mocking tend to use verifyNoMoreInteractions() very often, even in every test method. verifyNoMoreInteractions() is not recommended to use in every test method. verifyNoMoreInteractions() is a handy assertion from the interaction testing toolkit. Use it only when it's relevant. Abusing it leads to overspecified, less maintainable tests