如何测试枚举类型?

seb*_*seb 17 enums unit-testing hamcrest

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

public enum Month {
    January,
    February,
    ...
    December;
}
Run Code Online (Sandbox Code Playgroud)

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

assertThat(Month.January, is(notNullValue()));
Run Code Online (Sandbox Code Playgroud)

缺少"January"枚举会导致编译时错误,可以通过创建缺少的枚举类型来解决.

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

编辑:

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

在考虑了一下后,我将上面的Hamcrest声明更改为:

assertThat(Month.valueOf("January"), is(notNullValue()));
Run Code Online (Sandbox Code Playgroud)

当1月不存在时,该声明现在抛出NPE.这种方法有什么问题吗?

abe*_*t80 20

对于枚举,我只在它们实际上有方法时测试它们.如果它是一个纯粹的价值枚举,就像你的例子,我会说不要打扰.

但是既然你热衷于测试它,那么使用你的第二个选项要好于第一个选项.第一个问题是,如果您使用IDE,那么枚举上的任何重命名也会重命名测试类中的那些.


Mik*_*der 9

我同意异常80.

对于枚举,我只在它们实际上有方法时测试它们.如果它是一个纯粹的价值枚举,就像你的例子,我会说不要打扰.

但是既然你热衷于测试它,那么使用你的第二个选项要好于第一个选项.第一个问题是,如果您使用IDE,那么枚举上的任何重命名也会重命名测试类中的那些.

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

对于所有测试驱动开发,围绕Enums方法的测试可以减少代码库中的错误数量.

简单的例子

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));
    }
}
Run Code Online (Sandbox Code Playgroud)


Mar*_*ath 5

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

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


小智 5

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

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);
}
Run Code Online (Sandbox Code Playgroud)

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