我的一位同事在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文档警告不要这样做(https://static.javadoc.io/org.mockito/mockito-core/2.18.0/org/mockito/Mockito.html#finding_redundant_invocations):
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
我们谈到了这一点,他认为,如果测试代码将来发生变化(在示例代码中添加新的依赖方法调用,例如dependency3.doOtherC(),理论上可能会发生,但不一定必须),引入此类更改的开发人员可能不会记得使用相关检查更新测试(实际上已经在我们的项目中发生了几次)。通过使用verifyNoMoreInteractions()检测此类新更改而导致测试失败将迫使他们更新测试。
由于我负责代码审查,因此我必须对此类解决方案采取立场。虽然Mockito文件明显反对,但我必须承认,在这种特定情况下,我看到了这种“防御性”验证的目的。
在这种情况下这种解决方案是否可以接受?有没有其他方法可以确保更新测试?
答案 0 :(得分:0)
TestedClass testedObject;
应使用@InjectMock
进行注释,并命名为cut
(Class Unter Test)。 verifyNoMoreInteractions()
,但是
就像所有“扩张”方法一样,如果可能的话,你应该避免它。所以
如果函数不使用它的类的任何依赖,你不需要调用verifyNo..
- 但如果你不确定这是否会永远这样说,你可以/可以。TL;博士;使用它 - 或不是:就像宗教或政治一样 - 每个人都喜欢这样做(安全使用它但经常超载)