Readouble

Laravel 6.x モック

イントロダクションIntroduction

Laravelアプリケーションをテストするとき、アプリケーションの一部分を「モック」し、特定のテストを行う間は実際のコードを実行したくない場合があります。たとえば、イベントを発行するコントローラをテストする時は、実際に実行したくないイベントリスナをモックしたいと思うことでしょう。これにより、コントローラのHTTPレスポンスだけをテストでき、イベントリスナの実行は心配しなくて済みます。なぜなら、イベントリスナは自身のテストケースにおいて、テストできるからです。When testing Laravel applications, you may wish to "mock" certain aspects of your application so they are not actually executed during a given test. For example, when testing a controller that dispatches an event, you may wish to mock the event listeners so they are not actually executed during the test. This allows you to only test the controller's HTTP response without worrying about the execution of the event listeners, since the event listeners can be tested in their own test case.

Laravelにはイベント、ジョブ、ファサードを最初からモックできるヘルパが準備されています。これらのヘルパは主にMockery上で動作する便利なレイヤーを提供しているので、複雑なMockeryのメソッドコールを自分で作成する必要はありません。MockeryやPHPUnitを使用し、自身のモックやスパイを自由に作成してください。Laravel provides helpers for mocking events, jobs, and facades out of the box. These helpers primarily provide a convenience layer over Mockery so you do not have to manually make complicated Mockery method calls. You can also use Mockery[http://docs.mockery.io/en/latest/] or PHPUnit to create your own mocks or spies.

オブジェクトのモックMocking Objects

Laravelのサービスコンテナにより、アプリケーションへ依存注入されるオブジェクトをモックする場合は、モックしたインスタンスをコンテナへ、instance結合する必要があります。これによりコンテナへ対象のオブジェクトそのものを構築する代わりに、モックしたインスタンスオブジェクトを使用するように指示します。When mocking an object that is going to be injected into your application via Laravel's service container, you will need to bind your mocked instance into the container as an instance binding. This will instruct the container to use your mocked instance of the object instead of constructing the object itself:

use App\Service;
use Mockery;

$this->instance(Service::class, Mockery::mock(Service::class, function ($mock) {
    $mock->shouldReceive('process')->once();
}));

これをより便利にするため、Laravelのベーステストケースクラスでは、mockメソッドが使用できます。In order to make this more convenient, you may use the mock method, which is provided by Laravel's base test case class:

use App\Service;

$this->mock(Service::class, function ($mock) {
    $mock->shouldReceive('process')->once();
});

オブジェクトのいくつかのメソッドだけをモックする必要があるなら、partialMockメソッドが使えます。モックしていないメソッドは、呼び出し時に通常通り実行されます。You may use the partialMock method when you only need to mock a few methods of an object. The methods that are not mocked will be executed normally when called:

use App\Service;

$this->partialMock(Service::class, function ($mock) {
    $mock->shouldReceive('process')->once();
});

同様に、オブジェクトをスパイしたい場合は、Laravelの便利なMockery::spyラッパーであり、ベースのテストケースクラスで提供しているspyメソッドを用います。Similarly, if you want to spy on an object, Laravel's base test case class offers a spy method as a convenient wrapper around the Mockery::spy method:

use App\Service;

$this->spy(Service::class, function ($mock) {
    $mock->shouldHaveReceived('process');
});

Bus FakeBus Fake

モックの別の方法は、Busファサードのfakeメソッドを使用し、ジョブがディスパッチされないようにすることです。fakeを使用する場合、アサートはテスト下のコードが終了した時点で行われます。As an alternative to mocking, you may use the Bus facade's fake method to prevent jobs from being dispatched. When using fakes, assertions are made after the code under test is executed:

<?php

namespace Tests\Feature;

use App\Jobs\ShipOrder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Bus;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function testOrderShipping()
    {
        Bus::fake();

        // 注文の実行コード…

        Bus::assertDispatched(ShipOrder::class, function ($job) use ($order) {
            return $job->order->id === $order->id;
        });

        // ジョブがディスパッチされないことを宣言
        Bus::assertNotDispatched(AnotherJob::class);
    }
}

Event FakeEvent Fake

モックの別の方法は、Eventファサードのfakeメソッドを使用し、全イベントリスナが実行されないようにすることです。その後で、イベントがディスパッチされたことをアサートし、さらに受け取ったデータの検査もできます。fakeを使用する場合、アサートはテストを実施したコードの後に実行されます。As an alternative to mocking, you may use the Event facade's fake method to prevent all event listeners from executing. You may then assert that events were dispatched and even inspect the data they received. When using fakes, assertions are made after the code under test is executed:

<?php

namespace Tests\Feature;

use App\Events\OrderFailedToShip;
use App\Events\OrderShipped;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Event;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * 注文発送のテスト
     */
    public function testOrderShipping()
    {
        Event::fake();

        // 注文の実行コード…

        Event::assertDispatched(OrderShipped::class, function ($e) use ($order) {
            return $e->order->id === $order->id;
        });

        // イベントが2回ディスパッチされることをアサート
        Event::assertDispatched(OrderShipped::class, 2);

        // イベントがディスパッチされないことをアサート
        Event::assertNotDispatched(OrderFailedToShip::class);
    }
}

Note: note Event::fake()を呼び出した後は、イベントリスナは実行されなくなります。そのためたとえば、モデルのcreatingイベントでUUIDを生成するなど、イベントに結びつけたモデルファクトリの使用をテストする場合は、ファクトリを呼び出した後にEvent::fake()を呼び出す必要があります。{note} After calling Event::fake(), no event listeners will be executed. So, if your tests use model factories that rely on events, such as creating a UUID during a model's creating event, you should call Event::fake() after using your factories.

イベントのサブセットのFakeFaking A Subset Of Events

特定のイベントに対してだけ、イベントリスナをフェイクしたい場合は、fakefakeForメソッドに指定してください。If you only want to fake event listeners for a specific set of events, you may pass them to the fake or fakeFor method:

/**
 * 受注処理のテスト
 */
public function testOrderProcess()
{
    Event::fake([
        OrderCreated::class,
    ]);

    $order = factory(Order::class)->create();

    Event::assertDispatched(OrderCreated::class);

    // 他のイベントは通常通りにディスパッチされる
    $order->update([...]);
}

限定的なEvent FakeScoped Event Fakes

テストの一部分だけでイベントをフェイクしたい場合は、fakeForメソッドを使用します。If you only want to fake event listeners for a portion of your test, you may use the fakeFor method:

<?php

namespace Tests\Feature;

use App\Events\OrderCreated;
use App\Order;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    /**
     * 注文発送のテスト
     */
    public function testOrderProcess()
    {
        $order = Event::fakeFor(function () {
            $order = factory(Order::class)->create();

            Event::assertDispatched(OrderCreated::class);

            return $order;
        });

        // イベントは通常通りにディスパッチされ、オブザーバが実行される
        $order->update([...]);
    }
}

Mail FakeMail Fake

Mailファサードのfakeメソッドを使い、メールが送信されるのを防ぐことができます。その後で、Mailableがユーザーへ送信されたかをアサートし、受け取ったデータを調べることさえできます。Fakeを使用する場合、テスト対象のコードが実行された後で、アサートしてください。You may use the Mail facade's fake method to prevent mail from being sent. You may then assert that mailables[/docs/{{version}}/mail] were sent to users and even inspect the data they received. When using fakes, assertions are made after the code under test is executed:

<?php

namespace Tests\Feature;

use App\Mail\OrderShipped;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Mail;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function testOrderShipping()
    {
        Mail::fake();

        // Assert that no mailables were sent...
        Mail::assertNothingSent();

        // 注文の実行コード…

        Mail::assertSent(OrderShipped::class, function ($mail) use ($order) {
            return $mail->order->id === $order->id;
        });

        // メッセージが指定したユーザーに届いたことをアサート
        Mail::assertSent(OrderShipped::class, function ($mail) use ($user) {
            return $mail->hasTo($user->email) &&
                   $mail->hasCc('...') &&
                   $mail->hasBcc('...');
        });

        // mailableが2回送信されたことをアサート
        Mail::assertSent(OrderShipped::class, 2);

        // mailableが送られなかったことをアサート
        Mail::assertNotSent(AnotherMailable::class);
    }
}

バックグランドで送信するために、mailableをキュー投入している場合は、assertSentの代わりにassertQueuedメソッドを使用してください。If you are queueing mailables for delivery in the background, you should use the assertQueued method instead of assertSent:

Mail::assertQueued(...);
Mail::assertNotQueued(...);

Notification FakeNotification Fake

Notificationファサードのfakeメソッドを使用し、通知が送られるのを防ぐことができます。その後で、通知がユーザーへ送られたことをアサートし、受け取ったデータを調べることさえできます。Fakeを使用するときは、テスト対象のコードが実行された後で、アサートを作成してください。You may use the Notification facade's fake method to prevent notifications from being sent. You may then assert that notifications[/docs/{{version}}/notifications] were sent to users and even inspect the data they received. When using fakes, assertions are made after the code under test is executed:

<?php

namespace Tests\Feature;

use App\Notifications\OrderShipped;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Notifications\AnonymousNotifiable;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function testOrderShipping()
    {
        Notification::fake();

        // Assert that no notifications were sent...
        Notification::assertNothingSent();

        // 注文の実行コード…

        Notification::assertSentTo(
            $user,
            OrderShipped::class,
            function ($notification, $channels) use ($order) {
                return $notification->order->id === $order->id;
            }
        );

        // 通知が指定したユーザーへ送られたことをアサート
        Notification::assertSentTo(
            [$user], OrderShipped::class
        );

        // 通知が送られなかったことをアサート
        Notification::assertNotSentTo(
            [$user], AnotherNotification::class
        );

        // 通知がNotification::route()メソッドにより送られたことをアサート
        Notification::assertSentTo(
            new AnonymousNotifiable, OrderShipped::class
        );

        // Notification::route()メソッドで通知を現在のユーザーに送ったことをアサート
        Notification::assertSentTo(
            new AnonymousNotifiable,
            OrderShipped::class,
            function ($notification, $channels, $notifiable) use ($user) {
                return $notifiable->routes['mail'] === $user->email;
            }
        );
    }
}

Queue FakeQueue Fake

モックの代替として、Queueファサードのfakeメソッドを使い、ジョブがキューされるのを防ぐことができます。その後で、ジョブがキューへ投入されたことをアサートし、受け取ったデータの内容を調べることもできます。Fakeを使う場合は、テスト対象のコードを実行したあとで、アサートしてください。As an alternative to mocking, you may use the Queue facade's fake method to prevent jobs from being queued. You may then assert that jobs were pushed to the queue and even inspect the data they received. When using fakes, assertions are made after the code under test is executed:

<?php

namespace Tests\Feature;

use App\Jobs\AnotherJob;
use App\Jobs\FinalJob;
use App\Jobs\ShipOrder;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Queue;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function testOrderShipping()
    {
        Queue::fake();

        // ジョブが投入されていないことをアサート
        Queue::assertNothingPushed();

        // 注文の実行コード…

        Queue::assertPushed(ShipOrder::class, function ($job) use ($order) {
            return $job->order->id === $order->id;
        });

        // 特定のキューへジョブが投入されたことをアサート
        Queue::assertPushedOn('queue-name', ShipOrder::class);

        // ジョブが2回投入されたことをアサート
        Queue::assertPushed(ShipOrder::class, 2);

        // ジョブが投入されなかったことをアサート
        Queue::assertNotPushed(AnotherJob::class);

        // ジョブが指定したジョブチェーンで投入され、クラスが一致していることをアサート
        Queue::assertPushedWithChain(ShipOrder::class, [
            AnotherJob::class,
            FinalJob::class
        ]);

        // ジョブが指定したジョブチェーンで投入され、クラスとプロパティ両方が一致していることをアサート
        Queue::assertPushedWithChain(ShipOrder::class, [
            new AnotherJob('foo'),
            new FinalJob('bar'),
        ]);

        // ジョブチェーンを使わずに、ジョブが投入されたことをアサート
        Queue::assertPushedWithoutChain(ShipOrder::class);
    }
}

Storage FakeStorage Fake

とてもシンプルにファイルアップロードのテストを行うため、Storageファサードのfakeメソッドにより、UploadedFileクラスのファイル生成ユーティリティと組み合わされたフェイクディスクを簡単に生成できます。The Storage facade's fake method allows you to easily generate a fake disk that, combined with the file generation utilities of the UploadedFile class, greatly simplifies the testing of file uploads. For example:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Storage;
use Tests\TestCase;

class ExampleTest extends TestCase
{
    public function testAlbumUpload()
    {
        Storage::fake('photos');

        $response = $this->json('POST', '/photos', [
            UploadedFile::fake()->image('photo1.jpg'),
            UploadedFile::fake()->image('photo2.jpg')
        ]);

        // ひとつ以上のファイルが保存されたことをアサート
        Storage::disk('photos')->assertExists('photo1.jpg');
        Storage::disk('photos')->assertExists(['photo1.jpg', 'photo2.jpg']);

        // ひとつ以上のファイルが保存されなかったことをアサート
        Storage::disk('photos')->assertMissing('missing.jpg');
        Storage::disk('photos')->assertMissing(['missing.jpg', 'non-existing.jpg']);
    }
}

lightbulb">Tip!! fakeメソッドはデフォルトとして、一時ディレクトリ内の全ファイルを削除します。ファイルを残しておきたい場合は、代わりにpersistentFakeメソッドを使用してください。{tip} By default, the fake method will delete all files in its temporary directory. If you would like to keep these files, you may use the "persistentFake" method instead.

ファサードFacades

伝統的な静的メソッドの呼び出しと異なり、ファサードはモックできます。これにより伝統的な静的メソッドより遥かなアドバンテージを得られ、依存注入を使用する場合と同じテスタビリティを持てます。テスト時は、コントローラのLaravelファサード呼び出しを頻繁にモックしたくなります。例として、以下のようなコントローラアクションを考えてください。Unlike traditional static method calls, facades[/docs/{{version}}/facades] may be mocked. This provides a great advantage over traditional static methods and grants you the same testability you would have if you were using dependency injection. When testing, you may often want to mock a call to a Laravel facade in one of your controllers. For example, consider the following controller action:

<?php

namespace App\Http\Controllers;

use Illuminate\Support\Facades\Cache;

class UserController extends Controller
{
    /**
     * アプリケーションの全ユーザーリストの表示
     *
     * @return Response
     */
    public function index()
    {
        $value = Cache::get('key');

        //
    }
}

shouldReceiveメソッドを使用し、Cacheファサードへの呼び出しをモックできます。これはMockeryインスタンスを返します。ファサードはLaravelのサービスコンテナにより管理され、依存解決されていますので、典型的な静的クラスよりもかなり高いテスタビリティーを持っています。例としてCacheファサードへのgetメソッド呼び出しをモックしてみましょう。We can mock the call to the Cache facade by using the shouldReceive method, which will return an instance of a Mockery[https://github.com/padraic/mockery] mock. Since facades are actually resolved and managed by the Laravel service container[/docs/{{version}}/container], they have much more testability than a typical static class. For example, let's mock our call to the Cache facade's get method:

<?php

namespace Tests\Feature;

use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Cache;
use Tests\TestCase;

class UserControllerTest extends TestCase
{
    public function testGetIndex()
    {
        Cache::shouldReceive('get')
                    ->once()
                    ->with('key')
                    ->andReturn('value');

        $response = $this->get('/users');

        // ...
    }
}

Note: note Requestファサードをモックしてはいけません。代わりに、テスト実行時はgetpostのようなHTTPヘルパメソッドへ、望む入力を引数として渡してください。同様に、Configファサードはモックを使う代わりに、テストではConfig::setメソッドを呼び出してください。{note} You should not mock the Request facade. Instead, pass the input you desire into the HTTP helper methods such as get and post when running your test. Likewise, instead of mocking the Config facade, call the Config::set method in your tests.

章選択

設定

明暗テーマ
light_mode
dark_mode
brightness_auto システム設定に合わせる
テーマ選択
photo_size_select_actual デフォルト
photo_size_select_actual モノクローム(白黒)
photo_size_select_actual Solarized風
photo_size_select_actual GitHub風(青ベース)
photo_size_select_actual Viva(黄緑ベース)
photo_size_select_actual Happy(紫ベース)
photo_size_select_actual Mint(緑ベース)
コードハイライトテーマ選択

明暗テーマごとに、コードハイライトのテーマを指定できます。

テーマ配色確認
スクリーン表示幅
640px
80%
90%
100%

768px以上の幅があるときのドキュメント部分表示幅です。

インデント
無し
1rem
2rem
3rem
原文確認
原文を全行表示
原文を一行ずつ表示
使用しない

※ 段落末のEボタンへカーソルオンで原文をPopupします。

Diff表示形式
色分けのみで区別
行頭の±で区別
削除線と追記で区別

※ [tl!…]形式の挿入削除行の表示形式です。

テストコード表示
両コード表示
Pestのみ表示
PHPUnitのみ表示
和文変換

対象文字列と置換文字列を半角スペースで区切ってください。(最大5組各10文字まで)

本文フォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

コードフォント

総称名以外はCSSと同様に、"〜"でエスケープしてください。

保存内容リセット

localStrageに保存してある設定項目をすべて削除し、デフォルト状態へ戻します。

ヘッダー項目移動

キーボード操作