web-dev-qa-db-ja.com

Mockito / Powermockを使用して列挙型シングルトンクラスをモックする方法は?

列挙型シングルトンクラスをモックする方法がわかりません。

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を使用しています。

22
Sonwright Gomez

INSTANCEが返すものをスタブ化したい場合は、それを行うことができますが、それは一種の厄介です(リフレクションとバイトコード操作を使用)。 PowerMock 1.4.12/Mockito 1.9.0を使用して、3つのクラスを持つ簡単なプロジェクトを作成してテストしました。すべてのクラスは同じパッケージに含まれていました。

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());
    }
}

Whitebox.setInternalStateの呼び出しは、INSTANCEを、テスト内で操作できるモックオブジェクトに置き換えます。

26
Matt Lachman

モックするメソッドとのインターフェースを持っている

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
}
0
JavaExcel