何时应该模拟(mock)或不模拟外部/依赖的公共接口。

huangapple go评论103阅读模式
英文:

When should I mock or not mock external/dependent public interface

问题

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

我想知道是否需要对Dependency类进行模拟(考虑到它纯粹是逻辑,没有涉及数据库或外部REST调用)。

我在思考,如果不对Dependency类进行模拟,那么它无论如何都会被CUT(被测类)覆盖,
或者我应该对其进行模拟,并为Dependency类的公共接口编写单独的单元测试套件。

public class ClassUnderTest {
  @Autowired
  private Dependency dependency;

  public Object foo(){
    // do something
    var = dependeny.bar(args..);
    // do somethig
  }
}
public class Dependency {
  public Object bar(args..){
    // do something
  }
}
英文:

I am trying to write unit test for the following class

I was wondering if I need to mock the Dependency class (consider that it is purely logic no DB or external rest calls are made).

I was thinking if I will not mock the Dependency class, then anyway it will be covered by the CUT
or should I mock it and write separate unit test suite for Dependency class public interface.

public class ClassUnderTest {
  @Autowired
  private Dependency dependency;

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

答案1

得分: 3

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

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

英文:

The main idea of unit testing is to test units separately. Otherwise, it would be an integration test.

In this case, you need to write a separate test suite for Dependency, and mock the call to it in ClassUnderTest.

答案2

得分: 2

如果您编写单元测试套件,您可能希望进行模拟,尤其是如果您的依赖关系是纯逻辑。考虑以下场景:

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!
  }
}

在您的单元测试中,您会有类似以下的内容:

@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)));
}
英文:

If you're writing your unit test suite you probably want to mock it, even more if your dependency is pure logic. Consider the following scenario

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!
  }
}

In your unit test, you'll have something like

@Test
void testingClass() {
  assertThat(classUnderTest.doSomething(2, 2), is(equalTo(8)));
}

which will fail. However, your class under test is working fine! It's just delegating the task to another class

You can avoid this false positives by mocking properly your dependencies

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

答案3

得分: 2

你有两个单独的问题。

模拟的重点在于在单元测试中不使用依赖项来创建隐含行为。您希望单元测试对于您所测试的代码单元是明确的,以便能够识别回归,并且还可以声明您对 ClassUnderTest 在不同条件下行为的期望。

是否需要覆盖 Dependency 是一个涉及您编码标准的问题。一般而言,如果一个类如此简单,以至于您在考虑是否需要测试它,通常编写测试不应该是一个问题;而如果编写测试成为一个问题,那对我来说往往表明您真的应该在那里进行测试,因为您不确定的正是该代码区域是不透明的。

英文:

You have two separate question.

The point of mocking is to not have dependencies in your unit tests creating implicit behavior. You want unit tests to be explicit about the code unit you test to be able to identify regression and also declare your expectation how ClassUnderTest behaves in different conditions.

Whether you need to cover Dependency is a question concerning your coding standards. In general I find if a class is so simple that you ponder whether you need to test it, then usually writing the test should be a none issue and if writing a test is an issue to me that often enough indicates you really should have a test there, given you are unsure precisely because that code region is opaque.

huangapple
  • 本文由 发表于 2020年10月27日 18:47:23
  • 转载请务必保留本文链接:https://go.coder-hub.com/64552785.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定