模拟 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 方法也不起作用,因为生成的字节码使用窗帘后面的跳转表来转到正确的大小写...所以我想也许可以用PowerMock或其他东西来实现一些黑魔法。false

谢谢!

编辑

由于我拥有枚举,我认为我可以向值添加一个方法,从而完全避免切换问题;但我离开了这个问题,因为它仍然很有趣。


答案 1

下面是一个完整的示例。

代码几乎就像你的原始代码(只是简化了更好的测试验证):

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 = mock(MyEnum.class);
        when(C.ordinal()).thenReturn(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

答案 2

如果可以使用 Maven 作为构建系统,则可以使用更简单的方法。只需在测试类路径中使用附加常量定义相同的枚举即可。

假设您在源目录(src/main/java)下声明了枚举,如下所示:

package my.package;

public enum MyEnum {
    A,
    B
}

现在,您在测试源目录(src/test/java)中声明完全相同的枚举,如下所示:

package my.package

public enum MyEnum {
    A,
    B,
    C
}

测试看到带有“重载”枚举的 testclass 路径,您可以使用“C”枚举常量测试代码。然后,您应该看到您的非法争议异常。

在带有 maven 3.5.2、AdoptOpenJDK 11.0.3 和 IntelliJ IDEA 2019.3.1 的 Windows 下进行测试


推荐