【问题标题】:How to test enum types?如何测试枚举类型?
【发布时间】:2009-07-03 14:51:37
【问题描述】:

我目前正在尝试为一个小型库构建一套或多或少完整的单元测试。由于我们希望允许存在不同的实现,我们希望这组测试是 (a) 通用的,以便我们可以重新使用它来测试不同的实现,并且 (b) 尽可能完整。对于(b)部分,我想知道是否有测试枚举类型的最佳实践。例如,我有一个枚举如下:

public enum Month {
    January,
    February,
    ...
    December;
}

在这里,我想确保所有枚举类型都确实存在。这甚至有必要吗?目前我正在使用 Hamcrests assertThat,如下例所示:

assertThat(Month.January, is(notNullValue()));

缺少“January”枚举会导致编译时错误,可以通过创建缺少的枚举类型来修复。

我在这里使用 Java,但我不介意您的答案是否适用于其他语言。

编辑:

正如 mkato 和 Mark Heath 都指出,测试枚举可能没有必要,因为当您使用不存在的枚举类型时编译器不会编译。但我仍然想测试这些枚举,因为我们想构建一个单独的类似 TCK 的 test.jar,它将在不同的实现上运行相同的测试。所以我的问题更像是:测试枚举类型的最佳方法是什么?

再想一想后,我将上面的 Hamcrest 语句更改为:

assertThat(Month.valueOf("January"), is(notNullValue()));

当 1 月(还)不存在时,此语句现在会引发 NPE。这种方法有什么问题吗?

【问题讨论】:

    标签: unit-testing enums hamcrest


    【解决方案1】:

    对于枚举,我仅在它们实际上包含方法时对其进行测试。如果它是像您的示例一样的纯值枚举,我会说不要打扰。

    但由于您热衷于对其进行测试,因此使用第二种选择比第一种要好得多。第一个问题是,如果您使用 IDE,对枚举的任何重命名也会重命名测试类中的枚举。

    【讨论】:

    • 我有一个枚举,它有一个我想测试的方法,我是单元测试的新手,无法找到为该方法编写测试用例的方法,你能提供给我吗一个例子或帮助。
    • 如果 "assertThat(Month.January, is(notNullValue()));"在 OP 的问题中不足以作为你的例子,我认为你最好将它作为一个单独的问题提出并提供一个你正在尝试测试的例子。在我看来,您可能需要 JUnit 本身的帮助。
    【解决方案2】:

    我同意aberrant80

    对于枚举,我仅在它们实际上包含方法时对其进行测试。 如果它是像您的示例一样的纯值枚举,我会说不要 麻烦。

    但是由于您热衷于对其进行测试,因此您的第二个选择是 比第一个好多了。第一个问题是,如果你 使用 IDE,对枚举的任何重命名也会重命名 你的测试班。

    我将通过添加 Enum 的单元测试非常有用来扩展它。如果您在大型代码库中工作,则构建时间开始增加,并且单元测试可能是验证功能的更快方法(测试仅构建其依赖项)。另一个非常大的优势是其他开发人员不能无意中更改您的代码的功能(对于非常大的团队来说这是一个巨大的问题)。

    在所有测试驱动开发中,围绕枚举方法进行的测试可以减少代码库中的错误数量。

    简单示例

    public enum Multiplier {
        DOUBLE(2.0),
        TRIPLE(3.0);
    
        private final double multiplier;
    
        Multiplier(double multiplier) {
            this.multiplier = multiplier;
        }
    
        Double applyMultiplier(Double value) {
            return multiplier * value;
        }
    
    }
    
    public class MultiplierTest {
    
        @Test
        public void should() {
            assertThat(Multiplier.DOUBLE.applyMultiplier(1.0), is(2.0));
            assertThat(Multiplier.TRIPLE.applyMultiplier(1.0), is(3.0));
        }
    }
    

    【讨论】:

    • 我有一个枚举,它有一个我想测试的方法,我是单元测试的新手,无法找到为该方法编写测试用例的方法,你能提供我吗一个例子或帮助。
    • 感谢您提供示例。我也被卡住了,因为我不知道如何在 enum 类中测试方法。
    【解决方案3】:

    通常我会说这有点矫枉过正,但偶尔也会有为枚举编写单元测试的原因。

    有时,分配给枚举成员的值不得更改,否则旧持久数据的加载将失败。同样,不得删除明显未使用的成员。单元测试可用于防止开发人员在没有意识到影响的情况下进行更改。

    【讨论】:

      【解决方案4】:

      你可以测试是否有一些值,例如:

      for(MyBoolean b : MyBoolean.values()) {
          switch(b) {
          case TRUE:
              break;
          case FALSE:
              break;
          default:
              throw new IllegalArgumentException(b.toString());
      }
      
      for(String s : new String[]{"TRUE", "FALSE" }) {
          MyBoolean.valueOf(s);
      }
      

      如果有人删除或添加一个值,某些测试会失败。

      【讨论】:

        【解决方案5】:

        如果你在代码中使用所有月份,你的 IDE 不会让你编译,所以我认为你不需要单元测试。

        但是如果你是用反射来使用的话,即使你删除了一个月,它也会编译,所以放个单元测试是有效的。

        【讨论】:

        • 单元测试不知道你的月份将如何使用,更不知道它们将来如何使用。这意味着您应该为它们包含单元测试,即使如果所有月份都不存在,应用程序当前也不会编译。警告:在担心简单对象(例如没有方法的枚举)之前,确保您的复杂对象被单元测试正确覆盖。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-07-23
        • 2012-09-16
        • 2014-02-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多