Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何使用Mockito/Powermock模拟枚举单例类?_Java_Enums_Singleton_Mockito_Powermock - Fatal编程技术网

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

Java 如何使用Mockito/Powermock模拟枚举单例类?,java,enums,singleton,mockito,powermock,Java,Enums,Singleton,Mockito,Powermock,我不确定如何模拟枚举单例类 public enum SingletonObject{ INSTANCE; private int num; protected setNum(int num) { this.num = num; } public int getNum() { return num; } 我想在上面的示例中使用stub getNum(),但我不知道如何模拟实际的SingletonObject类。我认为使用Powermock来准备测试会有

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

public enum SingletonObject{
  INSTANCE;
  private int num;

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

  public int getNum() {
    return num;
  }
我想在上面的示例中使用stub getNum(),但我不知道如何模拟实际的SingletonObject类。我认为使用Powermock来准备测试会有所帮助,因为枚举本身就是最终的

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

这是在使用PowerMockito 1.4.10和Mockito 1.8.5。

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

SingletonObject.java SingletonConsumer.java SingletonConsumerTest.java
白盒.setInternalState
的调用将
实例
替换为可在测试中操作的模拟对象。

与要模拟的方法有接口

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
}
模拟接口

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
}

除了上面的Matt Lachman答案之外,在
SingleTonConsumerTest.class

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

这将删除以下内容:-最终类-匿名类-基元类型错误。

我不确定这是否是最好的方法,但在我的情况下,到目前为止它工作正常。我使用mockito内核和mockito内联(3.11.0),我在spy的帮助下模拟我的单例。以您的班级为例:

SingletonObject so = SingletonObject.INSTANCE;
private SingletonObject spySo = Mockito.spy(so);

@Before
public void setUp() {
    Mockito.doReturn(10).when(spySo).getNum();
}

@Test
public void simpleTest() {
    assertThat(spySo.getNum(), is(10));
}

检查类似的线程:谢谢Martin,我通读了该线程,它看起来是一种使用非枚举方式实现单例的方法,我能够正确地使用该方法进行模拟。但是,有没有办法模拟枚举单例类?据我所知,enum singleton类是在java 1.5之后声明singleton的推荐方法。singleton是邪恶的:)但是如何模拟SingletonObject.class呢?它会给MockitoException加上注释“Mockito不能模仿/刺探以下:-最终类-匿名类-基本类型”这使用了PowerMock。嗨,我得到了
java.lang.IllegalAccessException:Can not set static final
,而使用
Whitebox.setInternalState
。你知道为什么吗?你在你的测试类上使用了
@PrepareForTest
注释吗?我尝试了同样的方法,但是我的枚举构造函数仍然在执行,我不想这样。上面的解决方案也模拟枚举的构造函数吗?这个答案是最好的
SingletonObject so = SingletonObject.INSTANCE;
private SingletonObject spySo = Mockito.spy(so);

@Before
public void setUp() {
    Mockito.doReturn(10).when(spySo).getNum();
}

@Test
public void simpleTest() {
    assertThat(spySo.getNum(), is(10));
}