如何使用 Mockito/Powermock 模拟枚举单例类?单例对象.java辛格尔顿消费者.java单例消费者测试.java

2022-09-01 15:57:54

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

public enum SingletonObject{
  INSTANCE;
  private int num;

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

  public int getNum() {
    return num;
  }

我想在上面的例子中存根getNum(),但我不知道如何模拟实际的SingletonObject类。我认为使用Powermock来准备测试会有所帮助,因为枚举本质上是最终的。

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

这是使用PowerMockMockito 1.4.10和Mockito 1.8.5。


答案 1

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

单例对象.java

public enum SingletonObject {
    INSTANCE;
    private int num;

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

    public int getNum() {
        return num;
    }
}

辛格尔顿消费者.java

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

单例消费者测试.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());
    }
}

对 的调用将替换为可在测试中操作的模拟对象。Whitebox.setInternalStateINSTANCE


答案 2

具有要模拟的方法的接口

public interface SingletonInterface {
  int getNum();
}

让枚举实现接口

public enum SingletonObject implements SingletonInterface {
    INSTANCE;
    private int num;

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

    @Override
    public int getNum() {
        return num;
    }
}

模拟界面

@Test
public void test() {
  SingletonInterface singleton = Mockito.mock(SingletonInterface.class);
  when(singleton.getNum()).thenReturn(1); //does work
}

推荐