Unit testing 如何测试枚举类型?

Unit testing 如何测试枚举类型?,unit-testing,enums,hamcrest,Unit Testing,Enums,Hamcrest,我目前正试图为一个小型库构建一套或多或少完整的单元测试。因为我们希望允许存在不同的实现,所以我们希望这组测试是(a)通用的,以便我们可以重用它来测试不同的实现,并且(b)尽可能完整。对于(b)部分,我想知道是否有测试枚举类型的最佳实践。例如,我有一个枚举,如下所示: public enum Month { January, February, ... December; } 在这里,我想确保所有枚举类型都确实存在。这有必要吗?目前,我正在使用Hamcrestsa

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

public enum Month {
    January,
    February,
    ...
    December;
}
在这里,我想确保所有枚举类型都确实存在。这有必要吗?目前,我正在使用Hamcrests
assertThat
,如以下示例所示:

assertThat(Month.January, is(notNullValue()));
缺少“一月”枚举将导致编译时错误,可以通过创建缺少的枚举类型来修复该错误

我在这里使用Java,但我不介意你的答案是否是另一种语言

编辑:

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

仔细考虑后,我将上面的Hamcrest语句更改为:

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

这句话现在在一月还没到的时候抛出了一个NPE。这种方法有什么问题吗?

如果您在代码中使用所有的月份,IDE将不允许您编译,因此我认为您不需要单元测试


但是如果您将它们与反射一起使用,即使您删除一个月,它也会编译,因此进行单元测试是有效的。

通常我会说这是过分的,但偶尔也有理由为枚举编写单元测试


有时,分配给枚举成员的值决不能更改,否则旧版持久化数据的加载将失败。同样,显然未使用的成员也不得删除。单元测试可以用来防止开发人员在没有意识到其含义的情况下进行更改。

对于枚举,我只在它们实际包含方法时才对它们进行测试。如果它是一个纯值枚举,就像你的例子一样,我会说不用麻烦了

但是,既然您热衷于测试它,那么使用第二个选项比第一个选项要好得多。第一个的问题是,如果使用IDE,对枚举的任何重命名都会重命名测试类中的枚举。

我同意


对于枚举,我只在它们实际包含方法时才对它们进行测试。 如果它是一个纯值枚举,就像你的例子一样,我会说不要 麻烦

但是,既然您热衷于测试它,那么使用第二个选项是非常必要的 比第一次好多了。第一个的问题是如果你 使用IDE时,枚举上的任何重命名都会重命名中的枚举 你的测试课

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

对于所有测试驱动的开发,围绕枚举方法的测试可以减少代码库中的bug数量

简单示例

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));
    }
}

您可以通过以下示例测试是否有一些值:

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);
}

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

我有一个枚举,其中有一个方法需要测试,我是单元测试的新手,无法找到为该方法编写测试用例的方法,请您提供一个示例或帮助我完成此操作。如果“assertThat(Month.一月,is(notNullValue());”在OP的问题中,对你来说仅仅是一个例子是不够的,我认为你最好把它作为一个单独的问题来问,并提供一个你试图测试的例子。听起来你可能需要JUnit本身的帮助。我有一个enum,它有一个我想测试的方法,我是单元测试的新手,无法找到为该方法编写测试用例的方法,你能给我一个例子或帮助我做这件事吗。谢谢你提供了一个例子。我也被卡住了,因为我不知道如何在
enum
类中测试方法。单元测试不知道如何使用月份,更不知道将来如何使用月份。这意味着您应该为它们包含单元测试,即使如果没有所有月份,应用程序当前不会编译。警告:在担心简单对象(例如没有方法的枚举)之前,确保单元测试正确地覆盖了复杂对象。