Java 何时应模拟或不模拟外部/依赖公共接口

Java 何时应模拟或不模拟外部/依赖公共接口,java,unit-testing,junit,mockito,Java,Unit Testing,Junit,Mockito,我正在尝试为下面的类编写单元测试 我想知道是否需要对依赖类进行模拟,认为它是纯逻辑的,没有DB或外部REST调用。< /P> 我在想,如果我不模仿依赖类,那么不管怎样,它将被剪切覆盖 或者我应该模拟它并为依赖类公共接口编写单独的单元测试套件 public class ClassUnderTest { @Autowired private Dependency dependency; public Object foo(){ // do something var =

我正在尝试为下面的类编写单元测试

我想知道是否需要对依赖类进行模拟,认为它是纯逻辑的,没有DB或外部REST调用。< /P> 我在想,如果我不模仿依赖类,那么不管怎样,它将被剪切覆盖 或者我应该模拟它并为依赖类公共接口编写单独的单元测试套件

public class ClassUnderTest {
  @Autowired
  private Dependency dependency;

  public Object foo(){
    // do something
    var = dependeny.bar(args..);
    // do somethig
  }
}

单元测试的主要思想是分别测试单元。否则,这将是一个集成测试


在这种情况下,您需要为依赖项编写一个单独的测试套件,并在ClassUnderTest中模拟对它的调用。

如果您正在编写单元测试套件,您可能想要模拟它,如果依赖项是纯逻辑的,则更是如此。考虑下面的场景

public class ClassUnderTest {
  @Autowired
  private Dependency dependency;

  public int doSomething(int a, int b) {
    return dependency.add(a, b) * 2;
  }
}

public class Dependency {
  public int add(int a, int b) {
    return 0; // bug here!
  }
}
在单元测试中,您将得到如下结果

@Test
void testingClass() {
  assertThat(classUnderTest.doSomething(2, 2), is(equalTo(8)));
}
这将失败。然而,你的被测班级运转良好!这只是将任务委托给另一个类

通过正确地模拟依赖项,可以避免这种误报

@Test
void testingClass() {
  when(dependency.add(any(), any()).thenReturn(10);
  assertThat(classUnderTest.doSomething(2, 2), is(equalTo(20)));
}

你有两个问题

模拟的目的是在单元测试中不具有依赖项,从而创建隐式行为。您希望单元测试能够明确说明您测试的代码单元,以便能够识别回归,并声明您期望ClassUnderTest在不同条件下的行为


是否需要涵盖依赖性是一个与编码标准有关的问题。一般来说,我发现如果一个类非常简单,以至于您需要考虑是否需要对其进行测试,那么通常编写测试应该是一个无问题的问题,如果编写测试对我来说是一个问题,那么经常表明您确实应该在那里进行测试,因为您确实不确定,因为代码区域是不透明的。

这取决于依赖性是什么。考虑到你的例子是武断的,这是无法回答的。@Michael我对这个问题的回答很清楚,也很有道理,但我还是很想知道你的想法,idk,如果这有帮助的话,但是我的依赖类是一个简单的类,它执行一系列的震动转换。
@Test
void testingClass() {
  when(dependency.add(any(), any()).thenReturn(10);
  assertThat(classUnderTest.doSomething(2, 2), is(equalTo(20)));
}