イントロダクション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メソッド呼び出しを手作業で行う必要はありません。Laravel provides helpful methods for mocking events, jobs, and other 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.
オブジェクトのモックMocking Objects
Laravelのサービスコンテナを介してアプリケーションに注入されるオブジェクトをモックする場合、モックしたインスタンスをinstance
結合としてコンテナに結合する必要があります。これにより、オブジェクト自体を構築する代わりに、オブジェクトのモックインスタンスを使用するようコンテナへ指示できます。When mocking an object that is
going to be injected into your application via
Laravel's service
container[/docs/{{version}}/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;
use Mockery\MockInterface;
public function test_something_can_be_mocked()
{
$this->instance(
Service::class,
Mockery::mock(Service::class, function (MockInterface $mock) {
$mock->shouldReceive('process')->once();
})
);
}
これをより便利にするために、Laravelの基本テストケースクラスが提供するmock
メソッドを使用できます。たとえば、以下の例は上記の例と同じです。In order to make this more
convenient, you may use the mock
method
that is provided by Laravel's base test case class.
For example, the following example is equivalent to
the example above:
use App\Service;
use Mockery\MockInterface;
$mock = $this->mock(Service::class, function (MockInterface $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;
use Mockery\MockInterface;
$mock = $this->partialMock(Service::class, function (MockInterface $mock) {
$mock->shouldReceive('process')->once();
});
同様に、オブジェクトをスパイしたい場合のため、Laravelの基本テストケースクラスは、Mockery::spy
メソッドの便利なラッパーとしてspy
メソッドを提供しています。スパイはモックに似ています。ただし、スパイはスパイとテスト対象のコードとの間のやり取りを一度記録するため、コードの実行後にアサーションを作成できます。Similarly, if you want to
spy[http://docs.mockery.io/en/latest/reference/spies.html]
on an object, Laravel's base test case class offers
a spy
method as a convenient wrapper
around the Mockery::spy
method. Spies
are similar to mocks; however, spies record any
interaction between the spy and the code being
tested, allowing you to make assertions after the
code is executed:
use App\Service;
$spy = $this->spy(Service::class);
// …
$spy->shouldHaveReceived('process');
ファサードのモックMocking Facades
従来の静的メソッド呼び出しとは異なり、ファサード(リアルタイムファサードを含む)もモックできます。これにより、従来の静的メソッドに比べて大きな利点が得られ、従来の依存注入を使用した場合と同じくテストが簡単になります。テスト時、コントローラの1つで発生するLaravelファサードへの呼び出しをモックしたい場合がよくあるでしょう。例として、次のコントローラアクションについて考えてみます。Unlike traditional static method calls, facades[/docs/{{version}}/facades] (including real-time facades[/docs/{{version}}/facades#real-time-facades]) may be mocked. This provides a great advantage over traditional static methods and grants you the same testability that you would have if you were using traditional dependency injection. When testing, you may often want to mock a call to a Laravel facade that occurs 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 \Illuminate\Http\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');
// …
}
}
Warning!
Request
ファサードをモックしないでください。代わりに、テストの実行時に、get
やpost
などのHTTPテストメソッドに必要な入力を渡します。同様に、Config
ファサードをモックする代わりに、テストではConfig::set
メソッドを呼び出してください。Warning
You should not mock theRequest
facade. Instead, pass the input you desire into the HTTP testing methods[/docs/{{version}}/http-tests] such asget
andpost
when running your test. Likewise, instead of mocking theConfig
facade, call theConfig::set
method in your tests.
ファサードのスパイFacade Spies
ファサードでスパイしたい場合は、対応するファサードでspy
メソッドを呼び出します。スパイはモックに似ています。ただし、スパイはスパイとテスト対象のコードとの間のやり取りを一時的に記録しているため、コードの実行後にアサーションを作成できます。If you would like to
spy[http://docs.mockery.io/en/latest/reference/spies.html]
on a facade, you may call the spy
method on the corresponding facade. Spies are
similar to mocks; however, spies record any
interaction between the spy and the code being
tested, allowing you to make assertions after the
code is executed:
use Illuminate\Support\Facades\Cache;
public function test_values_are_be_stored_in_cache()
{
Cache::spy();
$response = $this->get('/');
$response->assertStatus(200);
Cache::shouldHaveReceived('put')->once()->with('name', 'Taylor', 10);
}
Bus FakeBus Fake
ジョブをディスパッチするコードをテストするときは、通常、特定のジョブがディスパッチされたことをアサートするが、実際にはジョブをキューに投入したり、実行したりは行う必要がありません。これは通常、ジョブの実行は、別のテストクラスでテストできるためです。When testing code that dispatches jobs, you typically want to assert that a given job was dispatched but not actually queue or execute the job. This is because the job's execution can normally be tested in a separate test class.
Bus
ファサードのfake
メソッドを使用して、ジョブがキューにディスパッチされないようにすることができます。それから、テスト対象のコードを実行した後、assertDispatched
メソッドとassertNotDispatched
メソッドを使用してアプリケーションがディスパッチしようとしたジョブを調べられます。You may use the Bus
facade's fake
method to prevent jobs
from being dispatched to the queue. Then, after
executing the code under test, you may inspect which
jobs the application attempted to dispatch using the
assertDispatched
and
assertNotDispatched
methods:
<?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 test_orders_can_be_shipped()
{
Bus::fake();
// 注文の実行コード…
// ジョブがディスパッチされたことをアサート
Bus::assertDispatched(ShipOrder::class);
// ジョブがディスパッチされなかったことをアサート
Bus::assertNotDispatched(AnotherJob::class);
// 同期的にジョブがディスパッチされたことをアサート
Bus::assertDispatchedSync(AnotherJob::class);
// 同期的にジョブがディスパッチされなかったことをアサート
Bus::assertNotDispatchedSync(AnotherJob::class);
// レスポンス送信後にジョブがディスパッチされたことをアサート
Bus::assertDispatchedAfterResponse(AnotherJob::class);
// レスポンス送信後にジョブがディスパッチされなかったことをアサート
Bus::assertNotDispatchedAfterResponse(AnotherJob::class);
// 1つもジョブがディスパッチされないことをアサート
Bus::assertNothingDispatched();
}
}
特定の「論理テスト」に合格するジョブがディスパッチされたことをアサートするために、上記利用可能なメソッドへクロージャを渡せます。指定する論理テストに合格するジョブが最低1つディスパッチされた場合、アサーションは成功します。たとえば、ジョブが特定の注文でディスパッチされたことをアサートしたい場合があります。You may pass a closure to the available methods in order to assert that a job was dispatched that passes a given "truth test". If at least one job was dispatched that passes the given truth test then the assertion will be successful. For example, you may wish to assert that a job was dispatched for a specific order:
Bus::assertDispatched(function (ShipOrder $job) use ($order) {
return $job->order->id === $order->id;
});
ジョブのサブセットのFakeFaking A Subset Of Jobs
もし、特定のジョブだけをディスパッチさせないようにしたい場合は、fake
メソッドへFakeするそのジョブを渡してください。If you only want to prevent
certain jobs from being dispatched, you may pass the
jobs that should be faked to the fake
method:
/**
* 注文処理のテスト
*/
public function test_orders_can_be_shipped()
{
Bus::fake([
ShipOrder::class,
]);
// ...
}
except
メソッドを使うと、指定したジョブ以外を全てFakeにできます。You may fake all jobs except for
a set of specified jobs using the
except
method:
Bus::fake()->except([
ShipOrder::class,
]);
ジョブチェーンJob Chains
Bus
ファサードのassertChained
メソッドを使用して、ジョブのチェーンがディスパッチされたことをアサートできます。assertChained
メソッドは、最初の引数にチェーンするジョブの配列を取ります。The Bus
facade's
assertChained
method may be used to
assert that a chain of
jobs[/docs/{{version}}/queues#job-chaining]
was dispatched. The assertChained
method accepts an array of chained jobs as its first
argument:
use App\Jobs\RecordShipment;
use App\Jobs\ShipOrder;
use App\Jobs\UpdateInventory;
use Illuminate\Support\Facades\Bus;
Bus::assertChained([
ShipOrder::class,
RecordShipment::class,
UpdateInventory::class
]);
上記の例でわかるように、チェーンジョブの配列はジョブのクラス名の配列です。ただし、実際のジョブインスタンスの配列を提供することもできます。そうすることで、Laravelは、ジョブインスタンスが同じクラスであり、アプリケーションがディスパッチしたチェーンジョブと同じプロパティ値を持つことを保証します。As you can see in the example above, the array of chained jobs may be an array of the job's class names. However, you may also provide an array of actual job instances. When doing so, Laravel will ensure that the job instances are of the same class and have the same property values of the chained jobs dispatched by your application:
Bus::assertChained([
new ShipOrder,
new RecordShipment,
new UpdateInventory,
]);
ジョブバッチJob Batches
Bus
ファサードのassertBatched
メソッドを使用して、ジョブのバッチがディスパッチされたことをアサートできます。assertBatched
メソッドへ渡すクロージャは、Illuminate\Bus\PendingBatch
のインスタンスを受け取ります。これはバッチ内のジョブを検査するために使用できます。The Bus
facade's
assertBatched
method may be used to
assert that a batch of
jobs[/docs/{{version}}/queues#job-batching]
was dispatched. The closure given to the
assertBatched
method receives an
instance of
Illuminate\Bus\PendingBatch
, which may
be used to inspect the jobs within the
batch:
use Illuminate\Bus\PendingBatch;
use Illuminate\Support\Facades\Bus;
Bus::assertBatched(function (PendingBatch $batch) {
return $batch->name == 'import-csv' &&
$batch->jobs->count() === 10;
});
ジョブ/バッチ間テストTesting Job / Batch Interaction
さらに、個々のジョブとその裏で動作しているバッチ間の相互作用をテストする必要がある場合があります。例えば、あるジョブがそのバッチの処理をキャンセルしたかどうかをテストする必要があるかもしれません。これを行うには、withFakeBatch
メソッドでFakeバッチをジョブへ割り当てる必要があります。withFakeBatch
メソッドは、ジョブのインスタンスとFakeバッチを含むタプルを返します。In addition, you may occasionally
need to test an individual job's interaction with
its underlying batch. For example, you may need to
test if a job cancelled further processing for its
batch. To accomplish this, you need to assign a fake
batch to the job via the withFakeBatch
method. The withFakeBatch
method
returns a tuple containing the job instance and the
fake batch:
[$job, $batch] = (new ShipOrder)->withFakeBatch();
$job->handle();
$this->assertTrue($batch->cancelled());
$this->assertEmpty($batch->added);
Event FakeEvent Fake
イベントをディスパッチするコードをテストするときは、イベントのリスナを実際に実行しないようにLaravelに指示することを推奨します。Event
ファサードのfake
メソッドを使用すると、リスナの実行を阻止し、テスト対象のコードを実行してから、assertDispatched
、assertNotDispatched
、assertNothingDispatched
メソッドを使用してアプリケーションがディスパッチするイベントをアサートできます。When testing code that dispatches
events, you may wish to instruct Laravel to not
actually execute the event's listeners. Using the
Event
facade's fake
method, you may prevent listeners from executing,
execute the code under test, and then assert which
events were dispatched by your application using the
assertDispatched
,
assertNotDispatched
, and
assertNothingDispatched
methods:
<?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 test_orders_can_be_shipped()
{
Event::fake();
// 注文の実行コード…
// イベントがディスパッチされたことをアサート
Event::assertDispatched(OrderShipped::class);
// イベントが2回ディスパッチされることをアサート
Event::assertDispatched(OrderShipped::class, 2);
// イベントがディスパッチされないことをアサート
Event::assertNotDispatched(OrderFailedToShip::class);
// イベントがディスパッチされなかったことをアサート
Event::assertNothingDispatched();
}
}
特定の「論理」に合格するイベントがディスパッチされたことをアサートするために、assertDispatched
またはassertNotDispatched
メソッドへクロージャを渡すことができます。指定する論理テストに合格するイベントが少なくとも1つディスパッチされた場合、アサーションは成功します。You may pass a closure to the
assertDispatched
or
assertNotDispatched
methods in order to
assert that an event was dispatched that passes a
given "truth test". If at least one event
was dispatched that passes the given truth test then
the assertion will be successful:
Event::assertDispatched(function (OrderShipped $event) use ($order) {
return $event->order->id === $order->id;
});
イベントリスナが特定のイベントをリッスンしていることを単にアサートしたい場合は、assertListening
メソッドを使用することができます。If you would simply like to
assert that an event listener is listening to a
given event, you may use the
assertListening
method:
Event::assertListening(
OrderShipped::class,
SendShipmentNotification::class
);
Warning!
Event::fake()
を呼び出した後、イベントリスナはすべて実行されません。したがって、モデルのcreating
イベント中にUUIDを作成するなど、イベントに依存するモデルファクトリをテストで使用する場合は、ファクトリを使用した後にEvent::fake()
を呼び出す必要があります。Warning
After callingEvent::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'screating
event, you should callEvent::fake()
after using your factories.
イベントのサブセットのFakeFaking A Subset Of Events
特定のイベントに対してだけ、イベントリスナをFakeしたい場合は、fake
かfakeFor
メソッドに指定してください。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 test_orders_can_be_processed()
{
Event::fake([
OrderCreated::class,
]);
$order = Order::factory()->create();
Event::assertDispatched(OrderCreated::class);
// その他のイベントは通常通りディスパッチされる
$order->update([...]);
}
except
メソッドを使用すると、指定するイベントセットを除外した、残りのイベントをFakeできます。You may fake all events except
for a set of specified events using the
except
method:
Event::fake()->except([
OrderCreated::class,
]);
限定的なEvent FakeScoped Event Fakes
テストの一部分だけでイベントをFakeしたい場合は、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\Models\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 test_orders_can_be_processed()
{
$order = Event::fakeFor(function () {
$order = Order::factory()->create();
Event::assertDispatched(OrderCreated::class);
return $order;
});
// イベントは通常どおりディスパッチされ、オブザーバが実行される
$order->update([...]);
}
}
HTTP FakeHTTP Fake
Http
ファサードのfake
メソッドでHTTPリクエスト作成時に、スタブした/ダミーのレスポンスを返すようにHTTPクライアントへ指示できます。送信するHTTPリクエストのFakeの詳細は、HTTPクライアントテストのドキュメントを調べてください。The Http
facade's
fake
method allows you to instruct the
HTTP client to return stubbed / dummy responses when
requests are made. For more information on faking
outgoing HTTP requests, please consult the HTTP
Client testing
documentation[/docs/{{version}}/http-client#testing].
Mail FakeMail Fake
Mail
ファサードのfake
メソッドを使用して、メールが送信されないようにすることができます。通常、メールの送信は、実際にテストするコードとは関係ありません。ほとんどの場合、Laravelが特定のメールを送信するよう指示されたとアサートするだけで十分です。You may use the Mail
facade's fake
method to prevent mail
from being sent. Typically, sending mail is
unrelated to the code you are actually testing. Most
likely, it is sufficient to simply assert that
Laravel was instructed to send a given
mailable.
Mail
ファサードのfake
メソッドを呼び出した後、mailablesがユーザーに送信されるように指示されたことをアサートし、Mailablesが受信したデータを検査することもできます。After calling the
Mail
facade's fake
method,
you may then assert that
mailables[/docs/{{version}}/mail] were
instructed to be sent to users and even inspect the
data the mailables received:
<?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 test_orders_can_be_shipped()
{
Mail::fake();
// 注文の実行コード…
// mailableが送信されなかったことをアサート
Mail::assertNothingSent();
// mailableが送られたことをアサート
Mail::assertSent(OrderShipped::class);
// 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(OrderShipped::class);
Mail::assertNotQueued(OrderShipped::class);
Mail::assertNothingQueued();
特定の「論理テスト」に合格したMailableが送信されたことをアサートするために、assertSent
、assertNotSent
、assertQueued
、assertNotQueued
メソッドにクロージャを渡すこともできます。指定する論理テストに合格するMailableが少なくとも1つ送信された場合、アサーションは成功します。You may pass a closure to the
assertSent
, assertNotSent
,
assertQueued
, or
assertNotQueued
methods in order to
assert that a mailable was sent that passes a given
"truth test". If at least one mailable was
sent that passes the given truth test then the
assertion will be successful:
Mail::assertSent(function (OrderShipped $mail) use ($order) {
return $mail->order->id === $order->id;
});
Mail
ファサードのアサートメソッドを呼び出すと、引数中のクロージャが受け取るMailableインスタンスは、Mailableを調べる便利なメソッドを提供しています。When calling the
Mail
facade's assertion methods, the
mailable instance accepted by the provided closure
exposes helpful methods for examining the
mailable:
Mail::assertSent(OrderShipped::class, function ($mail) use ($user) {
return $mail->hasTo($user->email) &&
$mail->hasCc('...') &&
$mail->hasBcc('...') &&
$mail->hasReplyTo('...') &&
$mail->hasFrom('...') &&
$mail->hasSubject('...');
});
Mailableインスタンスは、添付ファイルを調べるために便利なメソッドもいくつか持っています。The mailable instance also includes several helpful methods for examining the attachments on a mailable:
use Illuminate\Mail\Mailables\Attachment;
Mail::assertSent(OrderShipped::class, function ($mail) {
return $mail->hasAttachment(
Attachment::fromPath('/path/to/file')
->as('name.pdf')
->withMime('application/pdf')
);
});
Mail::assertSent(OrderShipped::class, function ($mail) {
return $mail->hasAttachment(
Attachment::fromStorageDisk('s3', '/path/to/file')
);
});
Mail::assertSent(OrderShipped::class, function ($mail) use ($pdfData) {
return $mail->hasAttachment(
Attachment::fromData(fn () => $pdfData, 'name.pdf')
);
});
メールが送信されなかったことを宣言する方法として、assertNotSent
とassertNotQueued
の2つの方法があるのにお気づきでしょうか。時には、メールが送信されなかったこと、またはキューに入れられなかったことをアサートしたい場合があります。これを実現するには、assertNothingOutgoing
やassertNotOutgoing
メソッドを使用してください。You may have noticed that there
are two methods for asserting that mail was not
sent: assertNotSent
and
assertNotQueued
. Sometimes you may wish
to assert that no mail was sent or
queued. To accomplish this, you may use the
assertNothingOutgoing
and
assertNotOutgoing
methods:
Mail::assertNothingOutgoing();
Mail::assertNotOutgoing(function (OrderShipped $mail) use ($order) {
return $mail->order->id === $order->id;
});
Mailable内容のテストTesting Mailable Content
Mailableの内容のテストと、Mailableが特定のユーザーへ「送信」されたことをアサートするテストは別にすることをお勧めします。Mailableの内容をテストする方法は、Mailablesのテストのドキュメントを参照してください。We suggest testing the content of your mailables separately from your tests that assert that a given mailable was "sent" to a specific user. To learn how to test the content of your mailables, check out our documentation on the testing mailables[/docs/{{version}}/mail#testing-mailables].
Notification FakeNotification Fake
Notification
ファサードのfake
メソッドを使用して、通知が送信されないようにすることができます。通常、通知の送信は、実際にテストしているコードとは関係ありません。ほとんどの場合、Laravelが特定の通知を送信するように指示したことをアサートするだけで十分です。You may use the
Notification
facade's fake
method to prevent notifications from being sent.
Typically, sending notifications is unrelated to the
code you are actually testing. Most likely, it is
sufficient to simply assert that Laravel was
instructed to send a given notification.
Notification
ファサードのfake
メソッドを呼び出した後、通知がユーザーへ送信されるように指示されたことをアサートし、通知が受信したデータを検査することもできます。After calling the
Notification
facade's fake
method, you may then assert that
notifications[/docs/{{version}}/notifications]
were instructed to be sent to users and even inspect
the data the notifications received:
<?php
namespace Tests\Feature;
use App\Notifications\OrderShipped;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Support\Facades\Notification;
use Tests\TestCase;
class ExampleTest extends TestCase
{
public function test_orders_can_be_shipped()
{
Notification::fake();
// 注文の実行コード…
// 通知がまったく送られていないことをアサート
Notification::assertNothingSent();
// 指定するユーザーに通知が送信されたことをアサート
Notification::assertSentTo(
[$user], OrderShipped::class
);
// 通知が送信されなかったことをアサート
Notification::assertNotSentTo(
[$user], AnotherNotification::class
);
// 指定した数の通知が送信されたことをアサート
Notification::assertCount(3);
}
}
特定の「論理テスト」に合格した通知が送信されたことをアサートするために、assertSentTo
またはassertNotSentTo
メソッドへクロージャを渡すこともできます。指定する論理テストに合格する通知が少なくとも1つ送信された場合、アサーションは成功します。You may pass a closure to the
assertSentTo
or
assertNotSentTo
methods in order to
assert that a notification was sent that passes a
given "truth test". If at least one
notification was sent that passes the given truth
test then the assertion will be
successful:
Notification::assertSentTo(
$user,
function (OrderShipped $notification, $channels) use ($order) {
return $notification->order->id === $order->id;
}
);
オンデマンド通知On-Demand Notifications
テストしているコードがオンデマンド通知を送る場合、assertSentOnDemand
メソッドにより、そのオンデマンド通知が送られたことをテストできます。If the code you are testing sends
on-demand
notifications[/docs/{{version}}/notifications#on-demand-notifications],
you can test that the on-demand notification was
sent via the assertSentOnDemand
method:
Notification::assertSentOnDemand(OrderShipped::class);
assertSentOnDemand
メソッドの第2引数にクロージャを渡し、オンデマンド通知が正しい「ルート(route)」アドレスへ送られたかを判定できます。By passing a closure as the
second argument to the
assertSentOnDemand
method, you may
determine if an on-demand notification was sent to
the correct "route" address:
Notification::assertSentOnDemand(
OrderShipped::class,
function ($notification, $channels, $notifiable) use ($user) {
return $notifiable->routes['mail'] === $user->email;
}
);
Queue FakeQueue Fake
Queue
ファサードのfake
メソッドを使用して、キュー投入するジョブをキュー投入しないでおくことができます。ほとんどの場合、キュー投入するジョブ自体は別のテストクラスでテストされる可能性が高いため、Laravelが特定のジョブをキューへ投入するように指示したことをアサートするだけで十分です。You may use the
Queue
facade's fake
method
to prevent queued jobs from being pushed to the
queue. Most likely, it is sufficient to simply
assert that Laravel was instructed to push a given
job to the queue since the queued jobs themselves
may be tested in another test class.
Queue
ファサードのfake
メソッドを呼び出した後、アプリケーションがジョブをキューに投入しようとしたことをアサートできます。After calling the
Queue
facade's fake
method, you may then assert that the application
attempted to push jobs to the queue:
<?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 test_orders_can_be_shipped()
{
Queue::fake();
// 注文の実行コード…
// ジョブまったく投入されなかったことをアサート
Queue::assertNothingPushed();
// ジョブが特定のキューへ投入されたことをアサート
Queue::assertPushedOn('queue-name', ShipOrder::class);
// ジョブが2回投入されたことをアサート
Queue::assertPushed(ShipOrder::class, 2);
// ジョブが投入されなかったことをアサート
Queue::assertNotPushed(AnotherJob::class);
}
}
特定の「論理テスト」に合格するジョブが投入されたことをアサートするために、assertPushed
またはassertNotPushed
メソッドにクロージャを渡すこともできます。指定する論理テストに合格するジョブが少なくとも1つ投入された場合、アサートは成功します。You may pass a closure to the
assertPushed
or
assertNotPushed
methods in order to
assert that a job was pushed that passes a given
"truth test". If at least one job was
pushed that passes the given truth test then the
assertion will be successful:
Queue::assertPushed(function (ShipOrder $job) use ($order) {
return $job->order->id === $order->id;
});
もし、特定のジョブだけをfakeし、他のジョブは通常通り実行させたい場合は、fake
メソッドにfakeするジョブのクラス名を渡します。If you only need to fake specific
jobs while allowing your other jobs to execute
normally, you may pass the class names of the jobs
that should be faked to the fake
method:
public function test_orders_can_be_shipped()
{
Queue::fake([
ShipOrder::class,
]);
// 注文の発送処理の実行…
// ジョブが2回キュー投入されることをアサート
Queue::assertPushed(ShipOrder::class, 2);
}
ジョブチェーンJob Chains
Queue
ファサードのassertPushedWithChain
メソッドとassertPushedWithoutChain
メソッドを使用して、投入したジョブのジョブチェーンを検査できます。assertPushedWithChain
メソッドは、最初の引数にプライマリジョブをとり、2番目の引数としてチェーンジョブの配列を取ります。The Queue
facade's
assertPushedWithChain
and
assertPushedWithoutChain
methods may be
used to inspect the job chain of a pushed job. The
assertPushedWithChain
method accepts
the primary job as its first argument and an array
of chained jobs as its second argument:
use App\Jobs\RecordShipment;
use App\Jobs\ShipOrder;
use App\Jobs\UpdateInventory;
use Illuminate\Support\Facades\Queue;
Queue::assertPushedWithChain(ShipOrder::class, [
RecordShipment::class,
UpdateInventory::class
]);
上記の例でわかるように、チェーンジョブの配列はジョブのクラス名の配列です。ただし、実際のジョブインスタンスの配列を提供することもできます。そうすることで、Laravelは、ジョブインスタンスが同じクラスであり、アプリケーションがディスパッチしたチェーンジョブと同じプロパティ値を持つことを保証します。As you can see in the example above, the array of chained jobs may be an array of the job's class names. However, you may also provide an array of actual job instances. When doing so, Laravel will ensure that the job instances are of the same class and have the same property values of the chained jobs dispatched by your application:
Queue::assertPushedWithChain(ShipOrder::class, [
new RecordShipment,
new UpdateInventory,
]);
assertPushedWithoutChain
メソッドを使用して、ジョブチェーンなしでジョブが投入されたことをアサートできます。You may use the
assertPushedWithoutChain
method to
assert that a job was pushed without a chain of
jobs:
Queue::assertPushedWithoutChain(ShipOrder::class);
Storage FakeStorage Fake
Storage
ファサードのfake
メソッドを使用すると、偽のディスクを簡単に生成できます。これをIlluminate\Http\UploadedFile
クラスのファイル生成ユーティリティと組み合わせると、ファイルアップロードのテストが大幅に簡素化できます。例をご覧ください。The Storage
facade's
fake
method allows you to easily
generate a fake disk that, combined with the file
generation utilities of the
Illuminate\Http\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 test_albums_can_be_uploaded()
{
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']);
// 指定したディレクトリが空であることをアサート
Storage::disk('photos')->assertDirectoryEmpty('/wallpapers');
}
}
fake
メソッドはデフォルトで、一時ディレクトリにあるすべてのファイルを削除します。これらのファイルを残しておきたい場合は、代わりにpersistentFake
メソッドを使用してください。ファイルアップロードのテストの詳細は、ファイルアップロードに関するHTTPテストドキュメントの情報を参照してください。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. For more information on testing file
uploads, you may consult the HTTP testing
documentation's information on file
uploads[/docs/{{version}}/http-tests#testing-file-uploads].
Warning!
image
メソッドには、GD拡張が必要です。Warning
Theimage
method requires the GD extension[https://www.php.net/manual/en/book.image.php].
時間操作Interacting With Time
テスト時、now
やIlluminate\Support\Carbon::now()
のようなヘルパが返す時間を変更したいことはよくあります。幸いなことに、Laravelのベース機能テストクラスは現在時間を操作するヘルパを用意しています。When testing, you may
occasionally need to modify the time returned by
helpers such as now
or
Illuminate\Support\Carbon::now()
.
Thankfully, Laravel's base feature test class
includes helpers that allow you to manipulate the
current time:
use Illuminate\Support\Carbon;
public function testTimeCanBeManipulated()
{
// 未来へ移行する
$this->travel(5)->milliseconds();
$this->travel(5)->seconds();
$this->travel(5)->minutes();
$this->travel(5)->hours();
$this->travel(5)->days();
$this->travel(5)->weeks();
$this->travel(5)->years();
// 時間を止め、クロージャ実行後、通常時刻へ戻す
$this->freezeTime(function (Carbon $time) {
// ...
});
// 過去へ移行する
$this->travel(-5)->hours();
// 特定の時間へ移行する
$this->travelTo(now()->subHours(6));
// 現在時刻へ戻る
$this->travelBack();
}