Java
Android
Kotlin
Mockito
More than 1 year has passed since last update.

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ファイルを用意します。

app/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
mock-maker-inline

または、mockito-coreの代わりにmockito-inlineアーティファクトを指定します。

build.gradle
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を使用することができます。

build.gradle
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_STUBSWARNに変更した場合は、エラーにはなりませんが、以下のようなヒントがコンソールに出力されます。

[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アノテーションが付与されていることに留意下さい。

以上です。