如何使用Mockito/Powermock模拟枚举单例类?

Son*_*mez 20 java singleton enums mockito powermock

我不确定如何模拟枚举单例类.

public enum SingletonObject{
  INSTANCE;
  private int num;

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

  public int getNum() {
    return num;
  }
Run Code Online (Sandbox Code Playgroud)

我想在上面的例子中存根getNum(),但我无法弄清楚如何模拟实际的SingletonObject类.我认为使用Powermock准备测试会有所帮助,因为枚举本身就是最终的.

//... rest of test code
@Test
public void test() {
  PowerMockito.mock(SingletonObject.class);
  when(SingletonObject.INSTANCE.getNum()).thenReturn(1); //does not work
}
Run Code Online (Sandbox Code Playgroud)

这是使用PowerMockMockito 1.4.10和Mockito 1.8.5.

Mat*_*man 26

如果你想要删除INSTANCE返回的内容,你可以这样做,但它有点讨厌(使用反射和字节码操作).我使用PowerMock 1.4.12/Mockito 1.9.0创建并测试了一个包含三个类的简单项目.所有课程都在同一个课程中.

SingletonObject.java

public enum SingletonObject {
    INSTANCE;
    private int num;

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

    public int getNum() {
        return num;
    }
}
Run Code Online (Sandbox Code Playgroud)

SingletonConsumer.java

public class SingletonConsumer {
    public String consumeSingletonObject() {
        return String.valueOf(SingletonObject.INSTANCE.getNum());
    }
}
Run Code Online (Sandbox Code Playgroud)

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());
    }
}
Run Code Online (Sandbox Code Playgroud)

调用Whitebox.setInternalState替换INSTANCE为您可以在测试中操作的模拟对象.

  • 但是你怎么能模拟 SingletonObject.class 呢?它将给 MockitoException 注释“Mockito 不能模拟/监视以下内容:-最终类-匿名类-原始类型” (2认同)
  • 我尝试了相同的方式,但我的枚举构造函数仍然被执行,我不想要.上面的解决方案是否也是enum的构造函数? (2认同)