Testing Java enum default case

In certain situations it may be desirable to test the default case of a switch statement even if at the current time all possible values of the enum are covered (e.g. in case in the future a new value is added and not covered in the switch statement). Whether or not this does always make sense is debatable but not the concern of this post.

To achieve this we must add an artificial value to our enum. For this, we use PowerMock and Mockito. Consider the following enum:

public enum Day {  
    MONDAY, FRIDAY 
}

Now, suppose an instance of Day is evaluated in the following method using a switch statement:

public void tellItLikeItIs(Day day) {  
    switch (day) {
        case MONDAY:
            System.out.println("Mondays are bad.");
            break;

        case FRIDAY:
            System.out.println("Fridays are better.");
            break;

        default:
            System.out.println("The other days are so-so.");
            break;
    }
}

In the current state of the Day enum, all cases are covered and the default statement is not executed. However we might want to ensure correct behaviour in the default case using a unit test in case other days are added later.

We implement our testing strategy as follows:

@PrepareForTest(Day.class)
public class DayTest extends BaseTest {

    @Mock
    private Day additionalDay;

    @Test
    public void testTellItLikeItIsDefaultCase()
    {
        Day[] values = Day.values();
        Day[] valuesAndAdditional = new Day[values.length + 1];
        System.arraycopy(values, 0, valuesAndAdditional, 0, values.length);

        // create additional, artificial Day
        PowerMockito.mockStatic(Day.class);

        Whitebox.setInternalState(additionalDay, "name", "ADDITIONAL_DAY");
        Whitebox.setInternalState(additionalDay, "ordinal", values.length);
        valuesAndAdditional[values.length] = additionalDay;

        when(Day.values()).thenReturn(
                valuesAndAdditional);

        tellItLikeItIs(additionalDay);

        // Tests for default case behaviour
        // ...
    }

Note that we need to annotate our Test with PrepareForTest bound to our enum, as we perform a static mock on it later. For our mocked enum value, we set the name and ordinal attributes accordingly as these are evaluated in the switch statement. Finally, we overwrite the return value of the values method of our enum to include the additional value.

Note that at this point in time there appears to be a bug in PowerMock which allows for correct mocking only when the enum-related method is executed first in the test class!

Ensuring that the method in question is executed first depends on your specific testing framework.

Lukas

Read more posts by this author.

Dortmund, Germany https://lukaspradel.com

Subscribe to Programming & Whisky

Get the latest posts delivered right to your inbox.

or subscribe via RSS with Feedly!