我目前正在尝试为一个小型库构建一组或多或少完整的单元测试。由于我们希望允许存在不同的实现,我们希望这组测试是(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。这种方法有什么问题吗?
答案 0 :(得分:18)
对于枚举,我只在它们实际上有方法时测试它们。如果它是一个纯粹的价值枚举,就像你的例子,我会说不要打扰。
但是既然你热衷于测试它,那么选择第二个选项要好于第一个选项。第一个问题是,如果您使用IDE,那么枚举上的任何重命名也会重命名测试类中的那些。
答案 1 :(得分:9)
我同意aberrant80。
对于枚举,我只在它们实际上有方法时测试它们。 如果它只是一个纯粹的价值枚举,就像你的例子,我会说不 烦。
但是因为你热衷于测试它,所以选择你的第二个选项是 比第一个好得多。第一个问题是,如果你 使用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));
}
}
答案 2 :(得分:4)
通常我会说它有点矫枉过正,但偶尔也有理由为枚举编写单元测试。
有时,分配给枚举成员的值必须永远不会更改,否则旧版持久数据的加载将失败。同样,不得删除明显未使用的成员。单元测试可用于防止开发人员在没有意识到影响的情况下进行更改。
答案 3 :(得分:3)
如果您在代码中使用了所有月份,那么您的IDE将无法编译,因此我认为您不需要进行单元测试。
但是如果你使用反射,即使你删除一个月,它也会编译,所以进行单元测试是有效的。
答案 4 :(得分:3)
你可以测试一下是否有一些值,例如:
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);
}
如果有人删除或添加了某个值,则某些测试会失败。