0

I have an enum class:-

public enum Action {
    LOGGED_IN("logged_in"), 
    LOGGED_OUT("logged_out"),
    private final String action;

    /**
     * @param action
     */
    private Action(String action) {
        this.action = action;
    }

    /**Fetches the action.
     * @return String action
     */
    public String getAction() {
        return this.action;
    }
}

I am writing the below Junit to mock this enum class so that i can add another enum value to this Action for junit testing.

@RunWith(PowerMockRunner.class)
public class TestClass{

    public Action action;

@Test
    @PrepareForTest(Action.class)
    public void testgetFeatureIdNull() NoSuchFieldException, SecurityException {
        Action dummy = PowerMockito.mock(Action.class);
        Field value=Action.class.getDeclaredField("value");
        value.setAccessible(true);
        Whitebox.setInternalState(dummy, "value", "dummy");
        Whitebox.setInternalState(dummy,"ordinal", 2);
        request = "{" + "   opportunityNumber: 45," + " id: 1," + "   " + " s: {" + "   id: 23"
                + " }" + "}";
        action = Action.LOGGED_IN;
        assertEquals(null, PatternGenertor.getFeatureid(dummy, request));
    }

When running this code i am getting the below error:-

java.lang.NoSuchFieldException: value
    at java.lang.Class.getDeclaredField(Unknown Source)

Can anyone please tell me where am i doing wrong?

Sunny
  • 858
  • 3
  • 17
  • 39
  • What makes you think the superclass of your enum class (i.e. `Enum`) has a field named "value"? – John Bollinger Jun 29 '18 at 20:01
  • no value field of the Enum class... – Sunny Jun 29 '18 at 20:03
  • 2
    Why would you want to add a third value to the enum? Surely, from the point of view of the test, it makes more sense to test how the code works with just the two values in the enum, not three? You should test the way the code _is_, not the way the code _might have been_. – Dawood ibn Kareem Jun 29 '18 at 20:03
  • I want the third value because i want to test how the code behaves if the user provides some dummy data which does not exist in the Action enum...This is also one of the scenerios which i need to cover as on this case the method under test will return a null value. – Sunny Jun 29 '18 at 20:07
  • But that's an entirely different scenario! Testing what happens if the user gives bad input is _not_ the same thing as changing the values in the actual enum. – Dawood ibn Kareem Jun 29 '18 at 20:14
  • As per my scenerio. The user will be giving any input an i will be mapping it to enum. – Sunny Jun 29 '18 at 20:16
  • No. Your program contains an enum with two values. You're saying you want to test a fictitious program where the enum has three values. In other words, you've stopped testing your actual code, and moved into the land of the hypothetical. By all means, test what your program does when the user provides bad data. But don't waste your time testing what a modified version of the program does in that case. – Dawood ibn Kareem Jun 29 '18 at 20:19

2 Answers2

1

I might give here an answer that doesn't really good fit for a question, but I'll try anyway. IMO you shouldn't really add values to Enum. It just doesn't make sense with enums.

Enum is something that contains a list of possible values used by the program. If you add more values to it in mock, it's like saying - hey, I don't want to test my code any more, but I want to test something that never happens in real life. This doesn't sound right.

Instead, probably you should ask yourself "what exactly do you want to test" and change a logic of your test so that it will rely only on "real" values returned from enum.

I can even say, that in my practice I have never had to mock an enum with any tool, although it probably doesn't contribute to the answer :)

In addition, you have to now use PowerMock which is a very heavy and unpleasant tool to work with (in fact, its considered by many our colleagues as something that should be used only if you have to test a legacy code that no-one wants to change ever).

halfer
  • 19,824
  • 17
  • 99
  • 186
Mark Bramnik
  • 39,963
  • 4
  • 57
  • 97
0

I was able to mock my enum and add a dummy value to it using the below code.

@Test
    @PrepareForTest(Action.class)
    public void testgetFeatureIdNull() throws  NoSuchFieldException, SecurityException, NoSuchMethodException {
        Action dummy = PowerMockito.mock(Action.class);
        Method value=Action.class.getSuperclass().getDeclaredMethod("ordinal");
        value.setAccessible(true);
        Field value1=Action.class.getSuperclass().getDeclaredField("name");
        value1.setAccessible(true);

        Whitebox.setInternalState(dummy, "name", "dummy");
        Whitebox.setInternalState(dummy,"ordinal", 2);
        PowerMockito.mockStatic(Action.class);

        PowerMockito.when(Action.values()).thenReturn(new Action[]{Action.LOGGED_IN,Action.LOGGED_OUT, dummy});

        request = "{" + "   opportunityNumber: 34," + " id: 1," + "   " + " s: {" + "   id: 23"
                + " }" + "}";
        assertNull(PatternGenertor.getFeatureid(dummy, request));
    }
Sunny
  • 858
  • 3
  • 17
  • 39
  • This test proves absolutely nothing about the behaviour of your program. If I were reviewing this code in the course of my job, I would ask you to remove it from the codebase. – Dawood ibn Kareem Jun 30 '18 at 01:24