1

tl;dr: How do I, at runtime -for the purpose of testing-, add another element to a enum? I'm sure there must be away using some byte manipulation library like how PowerMockito works etc. I do not consider this a duplicate of "Can I add and remove elements of enumeration at runtime in Java" because I'm willing to put up with the kind of byte-manipulation or class-loader hacks you wouldn't do in production code, because it's for a test.


I'm writing Java unit tests and running unit test coverage reports. The only lines I'm not able to reach are in the code where I have a default case on a switch statement with an enum where all the enums are covered by the cases.

enum Pet { CAT, DOG; }

and then code like

final String speak;
switch( myPet ){
    case CAT:
        speak = "meow";
        break;

    case DOG:
        speak = "ruff";
        break;

    default:
        throw new IllegalArgumentException( "should not get here" );
}
System.out.println( speak );

I need to have the default statement or javac will complain that final line is using speak which might not be initialized.

However, I cannot get that line covered because there are no other values, and I don't want to add an additional enum value to production code for the purposes of testing.

Community
  • 1
  • 1
Sled
  • 18,541
  • 27
  • 119
  • 168
  • 2
    The proper solution here is to accept that 100% code coverage is impossible when some of your lines are supposed to never be run. – Louis Wasserman Aug 22 '13 at 20:07
  • @LouisWasserman At this point, I'm more interested in what kind of class loader black magic and/or byte code manipulation it would take to make it work, rather than the actual effect, which itself would be at best a minor bonus. It's a learning opportunity more than anything. – Sled Aug 22 '13 at 20:12
  • The learning oppotunity is that, if you need to perform black magic, your objective is wrong? – Raedwald Aug 22 '13 at 22:20
  • Black magic teaches you about JVM internals. – Sled Aug 23 '13 at 13:56

1 Answers1

1

Aside from the answer you found where you can test this using PowerMock (with some limitations as to the test order it would appear), you could also go about this the other way which is to have a test that proves that the code is unreachable.

I.e. Make a test that iterates through all possible values of the enum and has no exception thrown and speak set appropriately.

This would capture the case whereby the enum is modified and a new value is added without the switch being updated.

Trevor Freeman
  • 7,112
  • 2
  • 21
  • 40
  • The goal of the question was 1) to learn how to work some black magic and 2) get 100% line coverage from our measuring tool. – Sled Aug 23 '13 at 13:58
  • @ArtB Fair enough, but the question does not mention that black magic was the goal. Furthermore, I would argue that if a line is provably unreachable, and you have a test case that proves that unreachability, then you do in fact have 100% test coverage. – Trevor Freeman Aug 23 '13 at 16:06
  • "byte [code] manipulation" is a synonym for black magic in my books. :) – Sled Aug 23 '13 at 16:38