列挙型シングルトンクラスをモックする方法がわかりません。
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を使用しています。
INSTANCEが返すものをスタブ化したい場合は、それを行うことができますが、それは一種の厄介です(リフレクションとバイトコード操作を使用)。 PowerMock 1.4.12/Mockito 1.9.0を使用して、3つのクラスを持つ簡単なプロジェクトを作成してテストしました。すべてのクラスは同じパッケージに含まれていました。
public enum SingletonObject {
INSTANCE;
private int num;
protected void setNum(int num) {
this.num = num;
}
public int getNum() {
return num;
}
}
public class SingletonConsumer {
public String consumeSingletonObject() {
return String.valueOf(SingletonObject.INSTANCE.getNum());
}
}
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
を、テスト内で操作できるモックオブジェクトに置き換えます。
モックするメソッドとのインターフェースを持っている
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
}