How to mock an enum singleton class using Mockito/Powermock?

enums, java, mockito, powermock, singleton

Solution

If you want to stub out what INSTANCE returns, you can do it but it's kind of nasty (using reflection & bytecode manipulation). I created & tested a simple project with three classes using the PowerMock 1.4.12 / Mockito 1.9.0. All classes were in the same package.

SingletonObject.java

public enum SingletonObject {
    INSTANCE;
    private int num;

    protected void setNum(int num) {
        this.num = num;
    }

    public int getNum() {
        return num;
    }
}

SingletonConsumer.java

public class SingletonConsumer {
    public String consumeSingletonObject() {
        return String.valueOf(SingletonObject.INSTANCE.getNum());
    }
}

SingletonConsumerTest.java

import static org.junit.Assert.*;
import static org.powermock.api.mockito.PowerMockito.*;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
import org.powermock.reflect.Whitebox;

@RunWith(PowerMockRunner.class)
@PrepareForTest({SingletonObject.class})
public class SingletonConsumerTest {
    @Test
    public void testConsumeSingletonObject() throws Exception {
        SingletonObject mockInstance = mock(SingletonObject.class);
        Whitebox.setInternalState(SingletonObject.class, "INSTANCE", mockInstance);

        when(mockInstance.getNum()).thenReturn(42);

        assertEquals("42", new SingletonConsumer().consumeSingletonObject());
    }
}

The call to the `Whitebox.setInternalState` replaces `INSTANCE` with a mock object that you can manipulate within your test.

Problem

I am unsure on how to mock an enum singleton class. ``` public enum SingletonObject{ INSTANCE; private int num; protected setNum(int num) { this.num = num; } public int getNum() { return num; } ``` I'd like to stub getNum() in the above example, but I can't figure out how to mock the actual SingletonObject class. I thought using Powermock to prepare the test would help since enums are inherently final. ``` //... rest of test code @Test public void test() { PowerMockito.mock(SingletonObject.class); when(SingletonObject.INSTANCE.getNum()).thenReturn(1); //does not work } ``` This is using PowerMockMockito 1.4.10 and Mockito 1.8.5.

Original source

Related problems