嘲笑Java枚举添加一个值来测试失败案例
我有一个枚举开关或多或少像这样:
public static enum MyEnum {A, B}
public int foo(MyEnum value) {
switch(value) {
case(A): return calculateSomething();
case(B): return calculateSomethingElse();
}
throw new IllegalArgumentException("Do not know how to handle " + value);
}
我想要测试覆盖所有行,但由于代码需要处理所有可能性,因此在交换机中没有相应的case语句的情况下,我无法提供值。
扩展枚举以添加额外的值是不可能的,只是嘲笑equals方法返回false
将不起作用,因为生成的字节码使用窗帘后面的跳转表来转到正确的案例...所以我已经认为PowerMock或许可以实现一些黑魔法。
谢谢!
编辑 :
因为我拥有枚举,所以我认为我可以在值中添加一个方法,从而完全避免切换问题; 但我仍然留下这个问题,因为它仍然很有趣。
这是一个完整的例子。
代码几乎和你原来的一样(只是简化了更好的测试验证):
public enum MyEnum {A, B}
public class Bar {
public int foo(MyEnum value) {
switch (value) {
case A: return 1;
case B: return 2;
}
throw new IllegalArgumentException("Do not know how to handle " + value);
}
}
这里是完整代码覆盖的单元测试,该测试适用于Powermock(1.4.10),Mockito(1.8.5)和JUnit(4.8.2):
@RunWith(PowerMockRunner.class)
public class BarTest {
private Bar bar;
@Before
public void createBar() {
bar = new Bar();
}
@Test(expected = IllegalArgumentException.class)
@PrepareForTest(MyEnum.class)
public void unknownValueShouldThrowException() throws Exception {
MyEnum C = PowerMockito.mock(MyEnum.class);
Whitebox.setInternalState(C, "name", "C");
Whitebox.setInternalState(C, "ordinal", 2);
PowerMockito.mockStatic(MyEnum.class);
PowerMockito.when(MyEnum.values()).thenReturn(new MyEnum[]{MyEnum.A, MyEnum.B, C});
bar.foo(C);
}
@Test
public void AShouldReturn1() {
assertEquals(1, bar.foo(MyEnum.A));
}
@Test
public void BShouldReturn2() {
assertEquals(2, bar.foo(MyEnum.B));
}
}
结果:
Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.628 sec
@Melloware
...执行switch()语句的代码java抛出一个java.lang.ArrayIndexOutOfBounds ...
我有着同样的问题。 使用新的Enum作为测试类中的第一个运行测试。 我用这个问题创建了一个bug:https://code.google.com/p/powermock/issues/detail?id=440
而不是使用一些激进的字节码操作来启用一个测试来foo
的最后一行,我将删除它并依靠静态代码分析来代替。 例如,IntelliJ IDEA具有“未使用大小写的Enum switch
语句”代码检查,如果缺少某个case
它将为foo
方法发出警告。