How to test default value in enum using mockito and testNg

java test invalid enum
how to mock switch case

I have a third party enum class like this:

package se.api;
public enum InvestigationResultStatus {
  PENDING("PendingResult.rr"),
  NEW("NewResult.rr"),
  MODIFIED("ModifiedResult.rr"),
  FINAL("FinalResult.rr"),
  PRELIMINARY("PreliminaryResult.rr"),
  ADDITIONAL("AdditionalResult.rr"),
  REJECTED("RejectedResult.rr"),
  COMPLETE("Path.Results.InvestigationInformation.Complete"),
  UNDEFINED("");

  private final String languageKey;

  private InvestigationResultStatus(String languageKey) {
    this.languageKey = languageKey;
  }

  public String getLanguageKey() {
    return this.languageKey;
  }
}

and in my code I create enum for this class

package se.dto;
public enum InvestigationResultStatus
{
   PENDING,
   NEW,
   MODIFIED,
   FINAL,
   PRELIMINARY,
   ADDITIONAL,
   REJECTED,
   UNDEFINED
}

to map these api enum to my enum i created enum mapper:

package se.mapper;

import se.dto.InvestigationResultStatus;

public class InvestigationResultStatusMapper
{
  public InvestigationResultStatus mapOmResultStatusToNovaResultStatus(final se.api.InvestigationResultStatus investigationResultStatus){
    switch (investigationResultStatus){
      case PENDING:
        return InvestigationResultStatus.PENDING;
      case NEW:
        return InvestigationResultStatus.NEW;
      case MODIFIED:
        return InvestigationResultStatus.MODIFIED;
      case FINAL:
        return InvestigationResultStatus.FINAL;
      case PRELIMINARY:
        return InvestigationResultStatus.PRELIMINARY;
      case ADDITIONAL:
        return InvestigationResultStatus.ADDITIONAL;
      case REJECTED:
        return InvestigationResultStatus.REJECTED;
      case UNDEFINED:
        return InvestigationResultStatus.UNDEFINED;
      default:
        throw new IllegalArgumentException("Unknown InvestigationResultStatus: " + investigationResultStatus);
    }
  }
}

Now I want to test the InvestigationResultStatusMapper class default case path and throw IllegalArgumentException. I search and try it in many ways.But mosta of the examples are in using powermockito.but i want mackito with testNg.How can I test it.I try it using this,

@Test(expectedExceptions = { IllegalArgumentException.class })
  public void testMapOmResultStatusToNovaResultStatus_whenHaveDefaultValue_thenThrowIllegalArgumentException()
  {
    se.api.InvestigationResultStatus investigationResultStatusNewEnum = mock(se.api.InvestigationResultStatus.class);
    Whitebox.setInternalState(investigationResultStatusNewEnum, "name", "DEFAULT");
    Whitebox.setInternalState(investigationResultStatusNewEnum, "ordinal", "DefaultResult.rr");

    se.api.InvestigationResultStatus investigationResultStatusCosmic = mock(se.api.InvestigationResultStatus.class);

    when(investigationResultStatusCosmic.values()).thenReturn(
        new se.api.InvestigationResultStatus[] { InvestigationResultStatus.PENDING, InvestigationResultStatus.NEW,
            se.api.InvestigationResultStatus.MODIFIED, InvestigationResultStatus.FINAL, InvestigationResultStatus.PRELIMINARY,
            se.api.InvestigationResultStatus.ADDITIONAL, InvestigationResultStatus.REJECTED,
            se.api.InvestigationResultStatus.COMPLETE, InvestigationResultStatus.UNDEFINED, investigationResultStatusNewEnum });

    investigationResultStatusMapper.mapOmResultStatusToNovaResultStatus(investigationResultStatusNewEnum);
  }

In this I'm unabale to mock enum(final) class using mockito

 @BeforeClass
  public void setUp()
  {
    investigationResultStatusMapper = new InvestigationResultStatusMapper();
    investigationResultStatusNewEnum = PowerMockito.mock(InvestigationResultStatus.class);


    Whitebox.setInternalState(investigationResultStatusNewEnum, "name", "TEST");
    Whitebox.setInternalState(investigationResultStatusNewEnum, "ordinal", 9);

    InvestigationResultStatus[] investigationResultStatuses = Arrays
        .copyOf(InvestigationResultStatus.values(), InvestigationResultStatus.values().length + 1);
    investigationResultStatuses[investigationResultStatuses.length - 1] = investigationResultStatusNewEnum;

    PowerMockito.mockStatic(InvestigationResultStatus.class);

    PowerMockito.when(InvestigationResultStatus.values()).thenReturn(
        investigationResultStatuses);
  }

  /**
   * Test Method for {@link InvestigationResultStatusMapper#mapOmResultStatusToNovaResultStatus(InvestigationResultStatus)}
   * extend the InvestigationResultStatus enum for DEFAULT throw {@link IllegalArgumentException})
   */
  @Test(expectedExceptions = {
      IllegalArgumentException.class }, expectedExceptionsMessageRegExp = "Unknown InvestigationResultStatus: TEST")
  public void testMapOmResultStatusToNovaResultStatus_whenHaveDefaultValue_thenThrowIllegalArgumentException()
  {
    investigationResultStatusMapper.mapOmResultStatusToNovaResultStatus(investigationResultStatusNewEnum);
  }

How to test default value in enum using mockito and testNg, How to test default value in enum using mockito and testNg. Testing Java enum default case, Testing Java enum default case To achieve this we must add an artificial value to our enum. For this, we use PowerMock and Mockito. you can create directly an instance in order to avoid mocks. Testing the Impossible. But how can we test for impossible enum values? PowerMock can mock final static methods, which allows us to extend the MyEnum.values() method with a new enum value. Here is our MyActionInvalidValueTest.java test (blatantly copied from this stackoverflow answer on mocking enums):

you can create directly an instance in order to avoid mocks.

@Test(expectedExceptions = { IllegalArgumentException.class })
public void testMapOmResultStatusToNovaResultStatus_whenHaveDefaultValue_thenThrowIllegalArgumentException()
{

  InvestigationResultStatus investigation = new InvestigationResultStatus();
  investigation.mapOmResultStatusToNovaResultStatus(-10000);
   ....

}

Testing Java enum default case, Testing Java enum default case To achieve this we must add an artificial value to our enum. For this, we use PowerMock and Mockito. For JUnit, it works out of the box because 2nd @Test has its own fields and its own mocks. Mockito with TestNG. Now, let us look at how stubbing in TestNG works, we’ll use Mockito to mock as well. Prerequisites. I am assuming that you have installed TestNG plugin in eclipse. Steps for creating Mockito TestNG example.

Wrong approach. First of all, the 3rd party enum has 9 entries, but your own enum has only 8. So when your mapping code receives COMPLETE it will throw that exception! But if your own enum would have 9 entries, and you just map them 1-1 ... what is the point of using your own enum here in the first place? (there might be good reasons to have it, but at this point, it doesn't add much value).

Beyond that problem, you should do this completely different:

You put these mappings into a Map object. Then write a unit tests that uses InvestigationResultStatus.values() to acquire an array with all valid InvestigationResultStatus constants. You make sure that your map knows how to map all these valid constants (for example by checking that you get a non-null return value). Additionally, you might have one test for each 3rd party constant to check for the expected result.

The key point here is: unfortunately, enums might change over time. So you absolutely want to know when additional constants are added to the 3rd enum.

In other words: the java language respectively the compiler makes sure that there can't be "invalid" instances of that 3rd party enum. When you have InvestigationResultStatus someEnumValue, then it is 100% clear that: either someValue is null, or it is one of the constants from that enum. Nothing else is possible here! Thus: no need to expect, check or handle "invalid" values.

Mastering Unit Testing Using Mockito and JUnit, The JUnit runner dependsonreflection to executethe tests. Usually and specify one of the following available enum MethodSorters constant: MethodSorters.JVM​: This This is the default value that doesn't guarantee the execution order. The void method that you want to test could either be calling other methods to get things done, processing the input parameters, or maybe generating some values or all of it. With Mockito, you can

Should one test the values of an enum using unit tests?, If you have an enum with values only (no methods as one could do in Java), and this enum is part of the business definition of the system,  By default value? on your classes I don't see that you are putting some value by default, you need to test some value that was put. For example: class A { setEnum(Type.DEFAULT_VALUE)} so a test on class A, A a = new A(); a.getEnumValue(); so you will have a value by default. – user10713028 Dec 4 '18 at 5:39

switch statement, unit-testing maintenance enum If you're going to add another value to the enum, you'd better add a case here too. time I write a switch statement anymore, it's because I'm checking the cases of an enum. Our Ada coding standard states that with switches on enums, explicit handling of all values, with no default is the  java,unit-testing,mockito,powermock You try to use deep stubbing without preparing your mock objects. Try WebTarget target = mock(WebTarget.class, Mockito.RETURNS_DEEP_STUBS); The difference is, that the mock without deep stubbing returns default values on method calls (usually null).

Creating mocks of enums with PowerMock - Mockito Cookbook, What we will discuss here is how to mock and stub (you will learn about stubbing more in Chapter 4, Stubbing Behavior of Mocks) an enum using PowerMock  Our goal is to test CalcService class methods, so we will mock AddService using Mockito rather than creating its instance. TestNG Mockito mock() example. Let’s look at the TestNG test class where we will mock AddService using Mockito.mock() method.

Comments
  • I still have the error.Therefore i moved to powermock and mock it.not got any solution from mockito
  • As said: you wrote hard to test production code. The fact that you now start using powermock ... basically means that you fight the symptom, not the root cause. Rest assured: in the long run, you are more efficient by investing in improving your designs, instead of using the more bizarre mocking frameworks to work around the issues that are caused by your design.
  • Honestly, that is not a good self answer. You should at least add some explanations what exactly you did upfront. The fact that you just changed to PowerMock is not really obvious, and worse: as you said yourself: it doesn't answer your real question, as you didn't ask about powermock initially.
  • next soft ,yes! but i want to test default case by passing value which are not in my enum.That's the case I mocked the Enum class.
  • I updated my answer, you can do that in order to throw IllegalArgumentException. @JayaniSumudini
  • next soft , I already have a one test case for test null, @Test(expectedExceptions = { NullPointerException.class }) public void testMapOmResultStatusToNovaResultStatus_whenHaveNull_thenThrowNullPointerException() { investigationResultStatusMapper.mapOmResultStatusToNovaResultStatus(null); } but it return a NullPointerException.not a IllegalArgumentException.I want to test default case path.
  • :V sorry I don't understand .. what you mean
  • By default value? on your classes I don't see that you are putting some value by default, you need to test some value that was put. For example: class A { setEnum(Type.DEFAULT_VALUE)} so a test on class A, A a = new A(); a.getEnumValue(); so you will have a value by default.