How to test enum types?
Asked Answered
T

6

31

I'm currently trying to build a more or less complete set of unit tests for a small library. Since we want to allow different implementations to exist we want this set of tests to be (a) generic, so that we can re-use it to test the different implementations and (b) as complete as possible. For the (b) part I'd like to know if there is any best-practice out there for testing enum types. So for example I have an enum as follows:

public enum Month {
    January,
    February,
    ...
    December;
}

Here I want to ensure that all enum types really exist. Is that even necessary? Currently I'm using Hamcrests assertThat like in the following example:

assertThat(Month.January, is(notNullValue()));

A missing "January" enum would result in a compile time error which one can fix by creation the missing enum type.

I'm using Java here but I don't mind if your answer is for a different language..

Edit:

As mkato and Mark Heath have both pointed out testing enums may not be necessary since the compiler won't compile when you are using an enum type which isn't there. But I still want to test those enums since we want to build a seperate TCK-like test.jar which will run the same test on different implementations. So my question was more meant to be like: What is the best way to test enum types?

After thinking about it a bit more I changed the Hamcrest statement above to:

assertThat(Month.valueOf("January"), is(notNullValue()));

This statement now throws a NPE when January is not there (yet). Is there anything wrong with this approach?

Titer answered 3/7, 2009 at 14:51 Comment(0)
E
40

For enums, I test them only when they actually have methods in them. If it's a pure value-only enum like your example, I'd say don't bother.

But since you're keen on testing it, going with your second option is much better than the first. The problem with the first is that if you use an IDE, any renaming on the enums would also rename the ones in your test class.

Exhilarate answered 9/7, 2009 at 13:9 Comment(2)
I have a enum that has one method that I want to test, I am a rookie in unit testing and can't figure out a way to write test cases for that method, can you please provide me an example or help to doing it.Coinage
If "assertThat(Month.January, is(notNullValue()));" in the OP's question is not enough of an example for you, I think you're better off asking it as a separate question and providing an example of what you're trying to test. Sounds to me like you might need help with JUnit itself.Exhilarate
T
20

I agree with aberrant80.

For enums, I test them only when they actually have methods in them. If it's a pure value-only enum like your example, I'd say don't bother.

But since you're keen on testing it, going with your second option is much better than the first. The problem with the first is that if you use an IDE, any renaming on the enums would also rename the ones in your test class.

I would expand on it by adding that unit testings an Enum can be very useful. If you work in a large code base, build time starts to mount up and a unit test can be a faster way to verify functionality (tests only build their dependencies). Another really big advantage is that other developers cannot change the functionality of your code unintentionally (a huge problem with very large teams).

And with all Test Driven Development, tests around an Enums Methods reduce the number of bugs in your code base.

Simple Example

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));
    }
}
Timeworn answered 24/10, 2011 at 21:39 Comment(2)
I have a enum that has one method that I want to test, I am a rookie in unit testing and can't figure out a way to write test cases for that method, can you please provide me an example or help to doing it.Coinage
Thank you for providing an example. I was stuck as well because I had no idea how to test a method within a enum class.Coker
A
7

Usually I would say it is overkill, but there are occasionally reasons for writing unit tests for enums.

Sometimes the values assigned to enumeration members must never change or the loading of legacy persisted data will fail. Similarly, apparently unused members must not be deleted. Unit tests can be used to guard against a developer making changes without realising the implications.

Assignment answered 3/7, 2009 at 15:1 Comment(0)
W
6

you can test if have exactly some values, by example:

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

If someone removes or adds a value, some of test fails.

Wadley answered 2/10, 2013 at 3:9 Comment(0)
I
4

If you use all of the months in your code, your IDE won't let you compile, so I think you don't need unit testing.

But if you are using them with reflection, even if you delete one month, it will compile, so it's valid to put a unit test.

Insufficiency answered 3/7, 2009 at 14:55 Comment(1)
Unit tests have no knowledge of how your months will be used and even less knowledge of how they might be used in the future. That implies that you should include unit tests for them, even if the application won't currently compile if all the months are not present. Caveat: Ensure your complex objects are properly covered by unit tests before worrying about simple ones (such as enums with no methods).Randi
S
2

This is a sample for what we have within our project.

public enum Role {

    ROLE_STUDENT("LEARNER"),
    ROLE_INSTRUCTOR("INSTRUCTOR"),
    ROLE_ADMINISTRATOR("ADMINISTRATOR"),
    ROLE_TEACHER("TEACHER"),
    ROLE_TRUSTED_API("TRUSTEDAPI");

    private final String textValue;

    Role(String textValue) {
        this.textValue = textValue;
    }

    public String getTextValue() {
        return textValue;
    }
}
class RoleTest {

    @Test
    void testGetTextValue() {

        assertAll(
                () -> assertEquals("LEARNER", Role.ROLE_STUDENT.getTextValue()),
                () -> assertEquals("INSTRUCTOR", Role.ROLE_INSTRUCTOR.getTextValue()),
                () -> assertEquals("ADMINISTRATOR", Role.ROLE_ADMINISTRATOR.getTextValue()),
                () -> assertEquals("TEACHER", Role.ROLE_TEACHER.getTextValue()),
                () -> assertEquals("TRUSTEDAPI", Role.ROLE_TRUSTED_API.getTextValue())
        );
    }
}

Scoreboard answered 20/5, 2022 at 8:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.