Mockito 2の変更点

[Mockito 2](http://site.mockito.org/)の変更点についてです。
Mockito 1ユーザの方に向けた内容となります。

## リリース方針について
2017/04に[リリース方針が変更](https://github.com/mockito/mockito/issues/911)されました。
以前は修正が入る度にリリースされていましたが、今後は重要なバージョン(基本的にはメジャー/マイナーバージョンが更新されたもの)のみが、JCenter/Mavenセントラルリポジトリより提供されます。

## Mockito 1からの変更点

主な変更点、追加機能を以下に記載します。
詳細は、[Wiki](https://github.com/mockito/mockito/wiki/What%27s-new-in-Mockito-2)、[リリースノート](https://github.com/mockito/mockito/blob/release/2.x/doc/release-notes/official.md)および[MockitoのJavadoc](https://javadoc.io/page/org.mockito/mockito-core/latest/org/mockito/Mockito.html#0)を確認下さい。

### finalクラス/メソッドをモックできるようになった

Mockito 1では[PowerMock](https://github.com/powermock/powermock)を必要としましたが、Mockito 2からはinline mock makerを有効にすることで、これらをモックすることが可能になりました。
デフォルトでfinal指定されているKotlinのクラスも、[kotlin-allopenプラグイン](https://blog.jetbrains.com/kotlin/2016/12/kotlin-1-0-6-is-here/)を使うことなくモックすることができます。

この機能を有効にするには、テスト用のリソースディレクトリに以下のMockMakerファイルを用意します。

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

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

```groovy:build.gradle
dependencies {
    //testCompile "org.mockito:mockito-core:+"
    testCompile "org.mockito:mockito-inline:+"
}
```

ただし、このアーティファクトは当該機能がデフォルトになるまでの過渡的なものなので、将来的には削除されるかもしれません。

この機能はInlineByteBuddyMockMakerというmock makerで提供されていますが、このクラスには[`@Incubating`](https://javadoc.io/page/org.mockito/mockito-core/latest/org/mockito/Incubating.html)アノテーションが付与されています。
`@Incubating`アノテーションは新しめのAPIに付与されるもので、ユーザからのフィードバックを期待することを示すものです。
フィードバック次第では(ほとんどないとは思いますが)APIの変更がありえますので、その点に留意下さい。

なお、staticメソッドやコンストラクタのモックには対応していませんので、それらをモックしたい場合は、これまで通りPowerMockが必要になります。

### Android端末用のライブラリが用意された

以前は[Dexmaker](https://github.com/linkedin/dexmaker)を必要としていましたが、Mockito 2.6からAndroid端末用のライブラリが提供されるようになりました。
mockito-androidをandroidTestCompileスコープのライブラリとして指定することで、Android端末上でMockitoを使用することができます。

```groovy:build.gradle
dependencies {
    androidTestCompile "org.mockito:mockito-android:+"
}
```

mockito-androidでは、Dexmakerで不可能だったパッケージプライベートクラスのモックを作成することができます。

なお、このアーティファクトでfinalクラス/メソッドをモックすることはできません。
(上記で挙げたinline mock makerもAndroidには対応していません)
こちらに関しては、拙作ではありますが、Android端末上でのfinalクラス/メソッドのモックを実現する[DexOpener](https://github.com/tmurakami/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にはマッチしません。

### モッククラスに対象クラスのアノテーションが付与されるようになった

例えば、対象クラスが以下であった場合

```java
@Foo
class Bar { ... }
```

モックのクラスにも`@Foo`が付与されます。

```java
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つのクラスが追加されています。

以下に使用例を示します。

```java
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)](https://javadoc.io/page/org.mockito/mockito-core/latest/org/mockito/quality/Strictness.html#STRICT_STUBS)います。

なお、Strictnessクラスには`@Incubating`アノテーションが付与されていますので、その点に留意下さい。

### MockitoSessionが導入された

Mockito 2.7より、MockitoJUnitRunner/MockitoRuleを使用できない環境向けに、MockitoSessionが提供されています。
モックの生成に`MockitoAnnotations#initMocks(Object)`を使用している場合は、MockitoSessionに置きかえることができます。

使用方法を以下に示します。

```java
private MockitoSession session;

@Before
public void setUp() {
    session = Mockito.mockitoSession().initMocks(this).startMocking();
}

@After
public void tearDown() {
    session.finishMocking();
}
```

上記のようにすると、`finishMocking()`のタイミングでStrictnessのモードに応じたチェックが行われます。

Strictnessを切りかえるには`strictness(Strictness)`メソッドを使用します。

```java
session = Mockito.mockitoSession()
    .initMocks(this)
    .strictness(Strictness.WARN)
    .startMocking();
```

Strictnessのデフォルトは`STRICT_STUBS`で、MockitoJUnitRunner/MockitoRuleの`WARN`よりも厳しいモードになっています。

なお、MockitoSessionにも`@Incubating`アノテーションが付与されていることに留意下さい。

以上です。