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

前端 未结 3 1169
春和景丽
春和景丽 2020-11-28 10:42

I am unsure on how to mock an enum singleton class.

public enum SingletonObject{
  INSTANCE;
  private int num;

  protected setNum(int num) {
    this.num =         


        
相关标签:
3条回答
  • 2020-11-28 11:09

    In addition to above Matt Lachman answer, create a object factory for power mock in SingleTonConsumerTest.class

    @ObjectFactory
    public IObjectFactory getObjectFactory() {
        return new org.powermock.modules.testng.PowerMockObjectFactory();
    }
    

    This will remove Mockito cannot mock/spy following: - final classes - anonymous classes - primitive types error.

    0 讨论(0)
  • 2020-11-28 11:14

    Have an interface with the methods you intend to mock

    public interface SingletonInterface {
      int getNum();
    }
    

    Let the enum implement the interface

    public enum SingletonObject implements SingletonInterface {
        INSTANCE;
        private int num;
    
        protected void setNum(int num) {
            this.num = num;
        }
    
        @Override
        public int getNum() {
            return num;
        }
    }
    

    Mock the interface

    @Test
    public void test() {
      SingletonInterface singleton = Mockito.mock(SingletonInterface.class);
      when(singleton.getNum()).thenReturn(1); //does work
    }
    
    0 讨论(0)
  • 2020-11-28 11:18

    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.

    0 讨论(0)
提交回复
热议问题