Mockito 2の変更点についてです。
Mockito 1ユーザの方に向けた内容となります。
リリース方針について
2017/04にリリース方針が変更されました。
以前は修正が入る度にリリースされていましたが、今後は重要なバージョン(基本的にはメジャー/マイナーバージョンが更新されたもの)のみが、JCenter/Mavenセントラルリポジトリより提供されます。
Mockito 1からの変更点
主な変更点、追加機能を以下に記載します。
詳細は、Wiki、リリースノートおよびMockitoのJavadocを確認下さい。
finalクラス/メソッドをモックできるようになった
Mockito 1ではPowerMockを必要としましたが、Mockito 2からはinline mock makerを有効にすることで、これらをモックすることが可能になりました。
デフォルトでfinal指定されているKotlinのクラスも、kotlin-allopenプラグインを使うことなくモックすることができます。
この機能を有効にするには、テスト用のリソースディレクトリに以下のMockMakerファイルを用意します。
mock-maker-inline
または、mockito-coreの代わりにmockito-inlineアーティファクトを指定します。
dependencies {
//testCompile "org.mockito:mockito-core:+"
testCompile "org.mockito:mockito-inline:+"
}
ただし、このアーティファクトは当該機能がデフォルトになるまでの過渡的なものなので、将来的には削除されるかもしれません。
この機能はInlineByteBuddyMockMakerというmock makerで提供されていますが、このクラスには@Incubating
アノテーションが付与されています。
@Incubating
アノテーションは新しめのAPIに付与されるもので、ユーザからのフィードバックを期待することを示すものです。
フィードバック次第では(ほとんどないとは思いますが)APIの変更がありえますので、その点に留意下さい。
なお、staticメソッドやコンストラクタのモックには対応していませんので、それらをモックしたい場合は、これまで通りPowerMockが必要になります。
Android端末用のライブラリが用意された
以前はDexmakerを必要としていましたが、Mockito 2.6からAndroid端末用のライブラリが提供されるようになりました。
mockito-androidをandroidTestCompileスコープのライブラリとして指定することで、Android端末上でMockitoを使用することができます。
dependencies {
androidTestCompile "org.mockito:mockito-android:+"
}
mockito-androidでは、Dexmakerで不可能だったパッケージプライベートクラスのモックを作成することができます。
なお、このアーティファクトでfinalクラス/メソッドをモックすることはできません。
(上記で挙げたinline mock makerもAndroidには対応していません)
こちらに関しては、拙作ではありますが、Android端末上でのfinalクラス/メソッドのモックを実現するDexOpenerというライブラリを提供しております。
よろしければお試し下さい。
ArgumentMatcherをラムダ式で記述できるようになった
Mockito 1ではArgumentMatcherは抽象クラスでした。
Mockito 2でSAMタイプのインタフェースに変更されたので、argThat(ArgumentMatcher)
でラムダ式を使うことができます。
any(Class)がnullにマッチしなくなった
any()
とany(Class)
が明確に別のメソッドになりました。
any()
はnullを含む任意の引数にマッチしますが、any(Class)
はnullにはマッチしません。
あと、これらのメソッドが定義されているクラスが、MatchersからArgumentMatchersへと変更されています。
anyXxx()系がnullにマッチしなくなった
anyString()
、anyList()
などのanyXxx()系マッチャーがnullにマッチしないようになりました。
anyObject()/anyVararg()が非推奨になった
Mockito 2ではany()
を使用します。
nullable(Class)の追加
isA(Class)
によく似たメソッドとしてnullable(Class)
が追加されています。
nullable(Class)
はnullまたは指定した型の引数にマッチしますが、isA(Class)
はnullにはマッチしません。
モッククラスに対象クラスのアノテーションが付与されるようになった
例えば、対象クラスが以下であった場合
@Foo
class Bar { ... }
モックのクラスにも@Foo
が付与されます。
Bar mock = mock(Bar.class);
assertTrue(mock.getClass().isAnnotationPresent(Foo.class));
Strictnessが導入された
Mockito 2.3より、Strictnessクラスが導入されています。
- LENIENT (Mockito 1のデフォルト、最もゆるい)
- WARN (Mockito 2のデフォルト)
- STRICT_STUBS (Mockito 3のデフォルトになる予定、最も厳しい)
の3つのモードがあり、モックの使用方法に関する例外を発生させたり、ヒントとなるメッセージを出力させたりすることができます。
また、MockitoJUnitRunnerにも
- MockitoJUnitRunner.Silent (
LENIENT
相当) - MockitoJUnitRunner.Strict (
WARN
相当、MockitoJUnitRunnerと同等) - MockitoJUnitRunner.StrictStubs (
STRICT_STUBS
相当)
の3つのクラスが追加されています。
以下に使用例を示します。
public class MyTest {
@Rule
public MockitoRule rule = MockitoJUnit.rule().strictness(Strictness.STRICT_STUBS);
@Mock
Foo foo;
@Test
public void test() {
when(foo.bar()).thenReturn("test");
}
class Foo {
String bar() {
return "";
}
}
}
上記のtest()
メソッドでは、when
句で設定したモックを使用していません。
このテストを実行すると、UnnecessaryStubbingExceptionがスローされます。
上記コードのSTRICT_STUBS
をWARN
に変更した場合は、エラーにはなりませんが、以下のようなヒントがコンソールに出力されます。
[MockitoHint] MyTest.test (see javadoc for MockitoHint):
[MockitoHint] 1. Unused -> at com.example.MyTest.test(MyTest.java:22)
LENIENT
に変更した場合は、エラーにもならず、メッセージも出力されません。
MockitoチームはSTRICT_STUBS
の使用を強く勧めて(Highly recommended)います。
なお、Strictnessクラスには@Incubating
アノテーションが付与されていますので、その点に留意下さい。
MockitoSessionが導入された
Mockito 2.7より、MockitoJUnitRunner/MockitoRuleを使用できない環境向けに、MockitoSessionが提供されています。
モックの生成にMockitoAnnotations#initMocks(Object)
を使用している場合は、MockitoSessionに置きかえることができます。
使用方法を以下に示します。
private MockitoSession session;
@Before
public void setUp() {
session = Mockito.mockitoSession().initMocks(this).startMocking();
}
@After
public void tearDown() {
session.finishMocking();
}
上記のようにすると、finishMocking()
のタイミングでStrictnessのモードに応じたチェックが行われます。
Strictnessを切りかえるにはstrictness(Strictness)
メソッドを使用します。
session = Mockito.mockitoSession()
.initMocks(this)
.strictness(Strictness.WARN)
.startMocking();
StrictnessのデフォルトはSTRICT_STUBS
で、MockitoJUnitRunner/MockitoRuleのWARN
よりも厳しいモードになっています。
なお、MockitoSessionにも@Incubating
アノテーションが付与されていることに留意下さい。
以上です。