Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
683 views
in Technique[技术] by (71.8m points)

unit testing - Mocking Java enum to add a value to test fail case

I have an enum switch more or less like this:

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

and I'd like to have all the lines covered by the tests, but as the code is expected to deal with all possibilities, I cannot supply a value without its corresponding case statement in the switch.

Extending the enum to add an extra value is not possible, and just mocking the equals method to return false won't work either because the bytecode generated uses a jump table behind the curtains to go to the proper case... So I've thought that maybe some black magic could be achieved with PowerMock or something.

Thanks!

edit:

As I own the enumeration, I've thought that I could just add a method to the values and thus avoid the switch issue completely; but I'm leaving the question as it's still interesting.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Here is a complete example.

The code is almost like your original (just simplified better test validation):

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

And here is the unit test with full code coverage, the test works with Powermock (1.4.10), Mockito (1.8.5) and 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));
    }
}

Result:

Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.628 sec

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...