【问题标题】:Write unit tests for an interface or each implementation?为接口或每个实现编写单元测试?
【发布时间】:2018-02-03 01:40:58
【问题描述】:

我有一个 Java 接口和几个实现。现在我想使用 Mockito 编写单元测试用例。

我的问题是,我应该为每个实现编写模拟测试用例还是只为接口编写模拟测试用例?在这种情况下,最佳做法是什么?我希望我的问题是有道理的。如果我遗漏了什么,请纠正我。

课程详情:

interface MessageQueue {
    add()
    poll()
    size()
}

class InMemoryMessageQueue implements MessageQueue {
    add() {
        //implementation
    }
    poll() {
        //implementation
    }
    size() {
        //implementation
    }
}

class FileSystemMessageQueue implements MessageQueue {
    add() {
        //implementation
    }
    poll() {
        //implementation
    }
    size() {
        //implementation
    }
}

目前我只有使用 Mockito 的 MessageQueue 接口的单元测试用例。

【问题讨论】:

  • 您是在尝试测试实现接口的类,还是其他?如果是前者,则不需要模拟任何东西(除非有其他依赖项);如果是后者,请在需要实现接口的地方使用模拟。
  • 正如您所说,您有多个接口的实现,如果您想测试所有不同的实现,那么建议为每个实现编写测试用例。
  • 由于我使用的是Mockito,我认为在模拟接口或实现方面没有区别,对吧? mockito 单元测试用例在没有任何改变的情况下可以很好地用于接口和实现。那我为什么要在所有实现测试中都有重复的代码呢?
  • 请发布“仅使用 mockito 的 MessageQueue 接口的单元测试用例。”,让我们了解您在这里做什么。

标签: java unit-testing mockito


【解决方案1】:

听起来您在这里混淆了一些细节,因为如果没有更多细节,“模拟测试用例”这个词就没有多大意义......

首先,假设您有三个接口实现,最好的做法是测试所有这三个。

只要您的实现没有依赖项,就根本不涉及任何模拟,因为...

其次,模拟用于测试依赖项。例如:

您的实现#2 必须从数据库加载数据。为此,它使用了一个类的实例,我们称之为DatabaseAccessor。通过调用这个DatabaseAccessor对象的方法,从数据库中获取数据。

现在,如果您想对实现 #2 进行单元测试,您实际上并不需要为此使用数据库,因为您会遇到很多问题。例如,如果数据库已关闭或处于不正确的状态,您的测试将失败,即使您真正想要测试的实现 #2 非常好。

这就是模拟的用武之地。不是使用实际的DatabaseAccessor 对象,而是模拟一个。换句话说,您创建了一个看起来像DatabaseAccessor 但实际上并不访问 Ddtabase 的对象。这种模拟的行为可以配置,例如,如果调用了一个方法,模拟返回一些有用的测试数据(同样,没有实际调用数据库,你只需告诉它“如果方法 X 被调用,这样做”)。

这样,您可以只专注于测试您的单元 - 实现 #2 - 而不必担心它的所有依赖项。这些被嘲笑,你知道,他们会表现得像他们应该的那样。

是的,使用 Mockito,您可以模拟实现和接口,但最好的做法是使用接口。如有其他问题,我建议您提供有关您的课程的更多详细信息。

【讨论】:

  • 请发布“仅使用 mockito 的 MessageQueue 接口的单元测试用例”之一,让我们了解您在这里做什么。
【解决方案2】:

让我们转向更面向对象的讨论。 假设我们编写了一个 Car 接口,它有一个 putFuel 之类的方法,

interface Car {
    void putFuel(FuelStation fs);
}

现在我想出了三个版本的汽车 -PetrolCar 实现汽车 -DieselCar 实现汽车 -CNGCar 实现 Car

现在 putFuel() 方法对于每个实现都会有很大的不同,例如加油站、柴油站和 CNG 站以及它们的 mock 相关依赖项。

因此,我应该为所有实现编写测试用例,因为每个实现都是不同的。 还要考虑到将来所有实现都可能具有接口可能没有的更多不同方法,因此为每个实现编写单独的单元测试用例非常有意义。

【讨论】:

    【解决方案3】:

    单元测试是为测试类的功能而编写的。接口只有空方法。您应该为每个类编写测试。

    【讨论】:

      猜你喜欢
      • 2021-12-24
      • 2011-05-08
      • 1970-01-01
      • 2011-09-30
      • 2011-01-28
      • 2015-07-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多