ユニットテストのMockitoとPowerMock
5463 ワード
モックって何?
ユニットテストでは、クラスのメソッドを独立して測定したい場合がありますが、このクラスは独立していません.他のクラスのメソッドとサービスを呼び出します.これにより、次の2つの問題が発生します.
この問題を解決するために、MockitoとPowerMockが誕生しました.この2つのツールは、外部で構築しにくいオブジェクトを仮想オブジェクトで置き換えることができ、ユニットテストを容易にします.両者の違いは、Mockitoがほとんどの標準的な単一測定caseに適していることであり、PowerMockは静的方法、プライベート方法など、より難しい問題を解決することができるということです.
Mockito
余計なことを言わないで,干物に行く.次の例では、テストするclassは
DummyService
DummyRepository
データベースからデータを取得するために使用されます.getDummyNameUpperCase()
メソッドはidに基づいてデータを取得し、このメソッドにはいくつかのデータ処理のロジックがあります.このロジックをテストしたい場合は、次のようにします.public class DummyServiceTest {
@Mock
private DummyRepository dummyRepository;
@InjectMocks
private DummyService dummyService;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void getDummyNameUpperCase() {
Dummy mockedDummy = new Dummy("dm1", "Dummy 1", "This is dummy 1", 2000, true);
when(dummyRepository.findById("dm1")).thenReturn(mockedDummy);
String result = dummyService.getDummyNameUpperCase("dm1");
verify(dummyRepository, times(1)).findById("dm1");
assertThat(result, is("DUMMY 1"));
}
}
経験上、ほとんどのプロジェクトでは依存注入フレームワーク(PicoContainer、Avalon、Excaliburなど)が使用されているため、ここでの例はSpringに基づいており、対応するMockitoコメント
@Mock
を使用して仮想オブジェクトを作成している.被測定classについては、@injectMocks
を用いて注釈すればよい.実際、mockの発生タイミングは、プログラムが「when-method-call-then-return」などの文に実行された場合、前例では、
when(dummyRepository.findById("dm1")).thenReturn(mockedDummy)
に実行された場合、mockはすでに発生している.プログラムがverify(dummyRepository, times(1)).findById("dm1")
クラスの文に実行されると、クラスの論理フローをテストする際に格外に有効なメソッドが呼び出されたことを確認できます.上記の例では、Mockitoの基本的な使い方を示していますが、実際のテストはそんなに簡単ではないかもしれません.たとえば、mockにオブジェクトを渡すオブジェクトをパラメータとして使用する場合は、
doAnswer
:@Test
public void testAddressCombination() {
Customer customer = new Customer("100089", "Zhang San", "1 Zhongguancun East Rd");
doAnswer(new Answer() {
@Override
public Customer answer(InvocationOnMock invocation) throws Throwable {
Object originalArgument = (invocation.getArguments())[0];
Customer param = (Customer) originalArgument;
param.setHost("TestHost");
return null;
}
}).when(hostService).expand(any(Customer.class));
when(addressService.getPLZForCustomer(customer)).thenReturn(47891);
doNothing().when(addressService).updateExternalSystems(customer);
String address = customerService.getAddressCombination(customer, true);
Mockito.verify(addressService, times(1)).updateExternalSystems(any(Customer.class));
assertThat(address, is("47891_1 Zhongguancun East Rd_TestHost"));
}
以上の2つの例は、通常の単一測定caseの大部分を拡張し、coverが除去するのに十分ですが、方法が静的であればどうすればいいのでしょうか.それは--PowerMockです.
PowerMock
PowerMockは基本的にすべてのMockitoがサポートできないcaseをcoverしています(ほとんどの場合静的メソッドですが、プライベートメソッドやコンストラクション関数の呼び出しもサポートできます).PowerMockはバイトコード操作を使用しているので、Junit runnerが付属しています.PowerMockを使用する場合は、必ず使用する
@PrepareForTest
測定対象クラスにコメントしてください.mockは実行されます.@RunWith(PowerMockRunner.class)
@PrepareForTest({StaticService.class})
public class DummyServiceTest {
@Mock
private DummyRepository dummyRepository;
@InjectMocks
private DummyService dummyService;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
}
@Test
public void readDummyDescriptionWithoutIOException() throws IOException {
String fileName = "DummyName";
mockStatic(StaticService.class);
when(StaticService.readFile(fileName)).thenReturn("Dummy");
String value = dummyService.readDummyDescription(fileName);
verifyStatic(times(1));
StaticService.readFile(fileName);
assertThat(value, equalTo("Dummy"));
}
}
上記の例から、PowerMockの書き方はMockitoとほぼ同じであることがわかります.主な原因はPowerMockがMockitoの特殊なAPIから派生したことです.Mavenの抜粋から、PowerMock Junit-moduleだけでなく、Mockito-APIも導入されていることがわかります.
org.powermock
powermock-module-junit4
1.6.4
test
org.powermock
powermock-api-mockito
1.6.4
test
なお、被験クラスに静的メソッドが含まれている場合は、
mockStatic()
メソッドを使用する必要があります.Mockitoと同様に,プログラムがwhen-then-mockingクラス文に実行されると,メソッドが正常に呼び出されたと考えられる.PowerMockのもう一つの使いやすい特性は、エージェントとして使用する場合
@PowerMockRunnerDelegate
です.例えばSpringではSpringJUnit 4 ClassRunnerが一般的に使われていますが、これで@PrepairForTest
使えなくなりますので:@RunWith(PowerMockRunner.class)
@PowerMockRunnerDelegate(Parameterized.class)
@PrepareForTest({StaticService.class})
public class DummyServiceTest {
...
}
まとめ
Mockitoは可読性が高く、使いやすいmockingテスト方法を提供しています.PowerMockはMockito-like APIを提供しています.Mockitoと基本的に似ています.静的方法、プライベート方法などの「問題解決方法」を解決します.