BDDMockitoのクイックガイド

BDDMockitoのクイックガイド

1. 概要

BDD用語は、最初にDan North – back in 2006によって造られました。

BDDは、アプリケーションの動作に焦点を当てた自然で人間が読める言語でテストを書くことを推奨します。

次の3つのセクション(Arrange、Act、Assert)に従ってテストを記述する明確に構造化された方法を定義します。

  • givenいくつかの前提条件(配置)

  • whenアクションが発生します(Act)

  • thenは出力を検証します(アサート)

The Mockito library is shipped with a BDDMockito class which introduces BDD-friendly APIs.このAPIを使用すると、given()を使用してテストを配置し、then()を使用してアサーションを作成する、よりBDDに適したアプローチをとることができます。

この記事では、BDDベースのMockitoテストをセットアップする方法について説明します。 また、Mockito APIとBDDMockito APIの違いについても説明し、最終的にはBDDMockitoAPIに焦点を当てます。

2. セットアップ

2.1. Mavenの依存関係

The BDD flavor of Mockito is part of the mockito-core library、開始するには、アーティファクトを含める必要があります。


    org.mockito
    mockito-core
    2.21.0

Mockitoの最新バージョンについては、Maven Centralを確認してください。

2.2. 輸入

次の静的インポートを含めると、テストが読みやすくなります。

import static org.mockito.BDDMockito.*;

BDDMockitoMockitoを拡張するため、従来のMockitoAPIによって提供される機能を見逃すことはありません。

3. モッキートvs. BDDMockito

Mockitoの従来のモックは、アレンジステップでwhen(obj)then*()を使用して実行されます。

後で、モックとの相互作用は、アサートステップでverify()を使用して検証できます。

BDDMockitoはさまざまなMockitoメソッドのBDDエイリアスを提供するため、(whenの代わりに)givenを使用してArrangeステップを記述できます。同様に、%を使用してAssertステップを記述できます。 (t4)s(verifyの代わりに)。

従来のMockitoを使用したテストボディの例を見てみましょう。

when(phoneBookRepository.contains(momContactName))
  .thenReturn(false);

phoneBookService.register(momContactName, momPhoneNumber);

verify(phoneBookRepository)
  .insert(momContactName, momPhoneNumber);

それがBDDMockitoとどのように比較されるか見てみましょう:

given(phoneBookRepository.contains(momContactName))
  .willReturn(false);

phoneBookService.register(momContactName, momPhoneNumber);

then(phoneBookRepository)
  .should()
  .insert(momContactName, momPhoneNumber);

4. BDDMockitoでモックする

PhoneBookRepository:をモックする必要があるPhoneBookServiceをテストしてみましょう

public class PhoneBookService {
    private PhoneBookRepository phoneBookRepository;

    public void register(String name, String phone) {
        if(!name.isEmpty() && !phone.isEmpty()
          && !phoneBookRepository.contains(name)) {
            phoneBookRepository.insert(name, phone);
        }
    }

    public String search(String name) {
        if(!name.isEmpty() && phoneBookRepository.contains(name)) {
            return phoneBookRepository.getPhoneNumberByContactName(name);
        }
        return null;
    }
}

BDDMockitoMockitoとして使用すると、固定または動的の値を返すことができます。 また、例外をスローすることもできます。

4.1. 固定値を返す

BDDMockito,を使用すると、モックオブジェクトのターゲットメソッドが呼び出されるたびに固定結果を返すようにMockitoを簡単に構成できます。

given(phoneBookRepository.contains(momContactName))
  .willReturn(false);

phoneBookService.register(xContactName, "");

then(phoneBookRepository)
  .should(never())
  .insert(momContactName, momPhoneNumber);

4.2. 動的な値を返す

BDDMockitoを使用すると、値を返すためのより高度な方法を提供できます。 入力に基づいて動的な結果を返すことができます。

given(phoneBookRepository.contains(momContactName))
  .willReturn(true);
given(phoneBookRepository.getPhoneNumberByContactName(momContactName))
  .will((InvocationOnMock invocation) ->
    invocation.getArgument(0).equals(momContactName)
      ? momPhoneNumber
      : null);
phoneBookService.search(momContactName);
then(phoneBookRepository)
  .should()
  .getPhoneNumberByContactName(momContactName);

4.3. 例外を投げる

Mockitoに例外をスローするよう指示するのは非常に簡単です。

given(phoneBookRepository.contains(xContactName))
  .willReturn(false);
willThrow(new RuntimeException())
  .given(phoneBookRepository)
  .insert(any(String.class), eq(tooLongPhoneNumber));

try {
    phoneBookService.register(xContactName, tooLongPhoneNumber);
    fail("Should throw exception");
} catch (RuntimeException ex) { }

then(phoneBookRepository)
  .should(never())
  .insert(momContactName, tooLongPhoneNumber);

givenwill*の位置をどのように交換したかに注目してください。これは、戻り値のないメソッドをモックする場合に必須です。

また、(anyeq)のような引数マッチャーを使用して、固定値に依存するのではなく、基準に基づいてモックするより一般的な方法を提供していることにも注意してください。

5. 結論

このクイックチュートリアルでは、BDDMockitoがMockitoテストにBDDの類似性をもたらす方法について説明し、MockitoBDDMockitoの違いのいくつかについて説明しました。

いつものように、ソースコードはover on GitHub –テストパッケージcom.example.bddmockito内にあります。