モッキング

要件: Mockery 1.0+

アプリケーションをテストする際に、特定のクラスを「モック」して、特定のテスト中に実際に呼び出されないようにすることがあります。たとえば、アプリケーションが支払いを開始するAPIと対話する場合、実際の支払いが行われないように、APIクライアントをローカルで「モック」したい場合があります。

始める前に、モッキングライブラリをインストールする必要があります。Mockeryをお勧めしますが、ニーズに合った他のライブラリを選択することもできます。

Mockeryを使い始めるには、Composerパッケージマネージャーを使用してインストールしてください。

1composer require mockery/mockery --dev

Mockeryの包括的なドキュメントはMockeryのウェブサイトにありますが、このセクションではモッキングの最も一般的なユースケースについて説明します。

メソッドの期待値

モックオブジェクトは、テスト対象のコードを分離し、アプリケーションの他の部分からの特定の動作や条件をシミュレートするために不可欠です。 `Mockery::mock()`メソッドを使用してモックを作成した後、`shouldReceive()`メソッドを呼び出すことで、特定のメソッドが呼び出されることを期待していることを示すことができます。

1use App\Repositories\BookRepository;
2use Mockery;
3 
4it('may buy a book', function () {
5 $client = Mockery::mock(PaymentClient::class);
6 $client->shouldReceive('post');
7 
8 $books = new BookRepository($client);
9 $books->buy(); // The API is not actually invoked since `$client->post()` has been mocked...
10});

上記と同じ構文を使用して、複数のメソッド呼び出しをモックすることができます。

1$client->shouldReceive('post');
2$client->shouldReceive('delete');

引数の期待値

メソッドの期待値をより具体的にするために、制約を使用してメソッド呼び出しの予想される引数リストを制限できます。これは、次の例に示すように、`with()`メソッドを使用して行うことができます。

1$client->shouldReceive('post')
2 ->with($firstArgument, $secondArgument);

引数マッチングの柔軟性を高めるために、Mockeryは特定の値の代わりに使用できる組み込みのmatcherクラスを提供しています。たとえば、特定の値を使用する代わりに、`Mockery::any()`を使用して任意の引数を一致させることができます。

1$client->shouldReceive('post')
2 ->with($firstArgument, Mockery::any());

`shouldReceive()`および`with()`を使用して定義された期待値は、メソッドが予期したとおりの引数で呼び出された場合にのみ適用されることに注意することが重要です。そうでない場合、Mockeryは例外をスローします。

1$client->shouldReceive('post')->with(1);
2 
3$client->post(2); // fails, throws a `NoMatchingExpectationException`

場合によっては、個々の引数に組み込みのmatcherを使用するのではなく、クロージャを使用して渡されたすべての引数を同時に一致させる方が適切な場合があります。 `withArgs()`メソッドは、予期されるメソッド呼び出しに渡されたすべての引数を受け取るクロージャを受け入れます。その結果、この期待値は、渡された引数によってクロージャがtrueと評価されるメソッド呼び出しにのみ適用されます。

1$client->shouldReceive('post')->withArgs(function ($arg) {
2 return $arg === 1;
3});
4 
5$client->post(1); // passes, matches the expectation
6$client->post(2); // fails, throws a `NoMatchingExpectationException`

戻り値

モックオブジェクトを扱う場合、`andReturn()`メソッドを使用して、モックされたメソッドから何を返すかをMockeryに指示できます。

1$client->shouldReceive('post')->andReturn('post response');

`andReturn()`メソッドに複数の戻り値を渡すことにより、戻り値のシーケンスを定義できます。

1$client->shouldReceive('post')->andReturn(1, 2);
2 
3$client->post(); // int(1)
4$client->post(); // int(2)

メソッドに渡された引数に基づいてメソッド呼び出しの戻り結果を計算する必要がある場合があります。これは、1つ以上のクロージャを受け入れる`andReturnUsing()`メソッドを使用して実現できます。

1$mock->shouldReceive('post')
2 ->andReturnUsing(
3 fn () => 1,
4 fn () => 2,
5 );

さらに、モックされたメソッドに例外をスローするように指示できます。

1$client->shouldReceive('post')->andThrow(new Exception);

メソッド呼び出し「回数」の期待値

メソッド呼び出しの予期される引数と戻り値を指定することに加えて、特定のメソッドが何回呼び出されるべきかの期待値を設定することもできます。

1$mock->shouldReceive('post')->once();
2$mock->shouldReceive('put')->twice();
3$mock->shouldReceive('delete')->times(3);
4// ...

メソッドが呼び出されるべき最小回数を指定するには、`atLeast()`メソッドを使用できます。

1$mock->shouldReceive('delete')->atLeast()->times(3);

Mockeryの`atMost()`メソッドを使用すると、メソッドを呼び出すことができる最大回数を指定できます。

1$mock->shouldReceive('delete')->atMost()->times(3);

このセクションの主な目的は、私たちが好むモッキングライブラリであるMockeryを紹介することです。ただし、Mockeryのより包括的な理解のために、公式ドキュメントを確認することをお勧めします。次に、Pestのプラグインを探求し、Pestエクスペリエンスをどのように向上させることができるかを見てみましょう:プラグイン