Mockito 为通用 @BeforeEach 设置方法中定义的存根抛出 UnnecessaryStubbingException

Mar*_*ers 15 java junit unit-testing mockito junit-jupiter

我有一个单元测试类,其中我的被测单元依赖于另一个类。使用 Mockito 模拟依赖关系,然后使用 JUnit 的@BeforeEach注释使用在每个单元测试之前运行的通用存根进行设置。请参阅下面的伪代码。

@ExtendWith(MockitoExtension.class)
public class FooFactoryTest {

    @Mock
    private BarDependency barDependency;

    @InjectMocks
    private FooFactory unitUnderTest;

    @BeforeEach
    public void setup() {
        when(barDependency.leftBar(any())).thenReturn(new Bar());
        when(barDependency.rightBar(any())).thenReturn(new Bar());
    }

   ... many tests ...

Run Code Online (Sandbox Code Playgroud)

此设置非常适合我的 10 个单元测试中的 9 个。不幸的是,我的一项测试失败并出现以下错误:

org.mockito.exceptions.misusing.UnnecessaryStubbingException: 
Unnecessary stubbings detected.
Clean & maintainable test code requires zero unnecessary code.
Following stubbings are unnecessary (click to navigate to relevant line of code):
  1. -> at nl.devillers.mockito.FooFactoryTest.setup(FooFactoryTest.java:69)
Please remove unnecessary stubbings or use 'lenient' strictness. More info: javadoc for UnnecessaryStubbingException class.
Run Code Online (Sandbox Code Playgroud)

现在,我理解了该错误以及抛出该错误的原因,因为在该特定测试中,我的被测单元很早就短路了,并且没有击中所有已设置的存根。我知道 Mockito 中有一个选项,但这会禁用对整个lenient类/项目的检查。

我的问题是:如何对一个特定的单元测试禁用这种严格性?

再说一次:我不想在班级或项目级别禁用严格性,因为我认为这是有价值的检查。我也不想将我的设置代码移至确实需要存根的测试,因为那样我必须将设置代码复制九次。在这种情况下,我只想禁用或跳过对此特定测试的检查。

Mar*_*ers 7

您可以通过使用未调用的存根重置模拟来避免在测试级别进行此检查。这是一个解决方法,但它允许您通过测试,而不必使模拟对整个测试类宽松或从设置方法中完全删除模拟。

要重置barDependency模拟,请将以下代码行添加到失败并带有UnnecessaryStubbingException.

Mockito.reset(barDependency);
Run Code Online (Sandbox Code Playgroud)

如果没有使用任何存根barDependency,您也可以将此行与其他安排一起放在测试的开头,这样会更干净一些。或者,将其放在测试方法的顶部,然后设置您确实需要的存根。这本质上会覆盖通用设置方法中正在设置的任何内容。


Bru*_*JCM 6

您还可以在 的代码中使用 lenient @BeforeEach,如下所示:

@BeforeEach
public void setup() {
    lenient().when(barDependency.leftBar(any())).thenReturn(new Bar());
    lenient().when(barDependency.rightBar(any())).thenReturn(new Bar());
}
Run Code Online (Sandbox Code Playgroud)

根据以下文档,这应该不是必需的UnnecessaryStubbingException:

仅当没有测试方法使用存根时,Mockito JUnit Runner 才会触发 UnnecessaryStubbingException。这意味着可以将默认存根放入“设置”方法或测试类构造函数中。其中一种测试方法需要至少使用一次默认存根。

  • 我也必须使用宽容。我看到文档,我不明白为什么它不起作用,但我正在使用mockito 4.0.0和JUnit 5.8.2和MockitoExtension,如果有另一个测试使用存根并不重要,每个测试都必须使用存根或失败。 (4认同)