테스트 시뮬레이터 조롱
~
이벤트 시뮬레이션
- 범위 이벤트 시뮬레이션
- 이메일 시뮬레이션
- 알림 시뮬레이션
- Facades
소개
Laravel 애플리케이션 테스트에서는 애플리케이션의 특정 기능의 동작을 "시뮬레이트"하여 해당 부분이 실제로 테스트에서 실행되는 것을 방지할 수 있습니다. 예를 들어 컨트롤러가 실행되는 동안 이벤트(Event)가 트리거되어 컨트롤러를 테스트할 때 이벤트가 실제로 실행되는 것을 방지합니다. 이를 통해 이벤트 트리거에 대해 걱정할 필요 없이 컨트롤러의 HTTP 응답만 테스트할 수 있습니다. 물론 별도의 테스트에서 이 이벤트 로직을 테스트할 수도 있습니다.
Laravel은 이벤트, 작업 및 외관 시뮬레이션을 위한 기본 도우미 기능을 제공합니다. 이러한 함수는 Mocker를 기반으로 캡슐화되어 있어 사용하기 매우 편리합니다. 복잡한 Mockery 함수를 수동으로 호출할 필요가 없습니다. 물론 Mockery를 사용하거나 PHPUnit을 사용하여 자신만의 에뮬레이터를 만들 수도 있습니다.
Mock Objects
Laravel의 서비스 컨테이너를 통해 애플리케이션에 주입될 객체를 모의할 때 모의 인스턴스를
인스턴스
로 컨테이너에 바인딩해야 합니다. 이는 실제 객체를 생성하는 대신 객체의 모의 인스턴스를 사용하도록 컨테이너에 지시합니다:instance
绑定到容器中。这将告诉容器使用对象的模拟实例,而不是构造对象的真身:use Mockery; use App\Service; $this->instance(Service::class, Mockery::mock(Service::class, function ($mock) { $mock->shouldReceive('process')->once(); }) );
为了让以上过程更加便捷,你可以使用 Laravel 的基本测试用例类提供
mock
方法:use App\Service;$this->mock(Service::class, function ($mock) { $mock->shouldReceive('process')->once(); });
任务模拟
作为模拟的替代方式,你可以使用
Bus
Facade 的fake
方法来防止任务被真正分发执行。使用 fake 的时候,断言一般出现在测试代码的后面:<?php namespace Tests\Feature; use Tests\TestCase;use App\Jobs\ShipOrder; use Illuminate\Support\Facades\Bus; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithoutMiddleware; 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); } }
事件模拟
作为 mock 的替代方法,你可以使用
Event
Facade 的fake
方法来模拟事件监听,测试的时候并不会真正触发事件监听器。然后你就可以测试断言事件运行了,甚至可以检查他们接收的数据。使用 fake 的时候,断言一般出现在测试代码的后面:<?php namespace Tests\Feature; use Tests\TestCase;use App\Events\OrderShipped; use App\Events\OrderFailedToShip; use Illuminate\Support\Facades\Event; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithoutMiddleware; class ExampleTest extends TestCase{ /** * 测试订单发送 */ public function testOrderShipping() { Event::fake(); // 执行订单发送... Event::assertDispatched(OrderShipped::class, function ($e) use ($order) { return $e->order->id === $order->id; }); // 断言一个事件被发送了两次... Event::assertDispatched(OrderShipped::class, 2); // 未分配断言事件... Event::assertNotDispatched(OrderFailedToShip::class); } }
{note} 调用
Event::fake()
后不会执行事件监听。所以,你基于事件的测试必须使用工厂模型,例如,在模型的creating
事件中创建 UUID ,你应该调用Event::fake()
之后 使用工厂模型。模拟事件的子集
如果你只想为特定的一组事件模拟事件监听器,你可以将它们传递给
fake
或fakeFor
方法:/** * 测试订单流程 */ public function testOrderProcess(){ Event::fake([ OrderCreated::class, ]); $order = factory(Order::class)->create(); Event::assertDispatched(OrderCreated::class); // 其他事件照常发送... $order->update([...]); }
Scoped 事件模拟
如果你只想为部分测试模拟事件监听,则可以使用
fakeFor
<?php namespace Tests\Feature; use App\Order;use Tests\TestCase; use App\Events\OrderCreated; use Illuminate\Support\Facades\Event; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithoutMiddleware; class ExampleTest extends TestCase{ /** * 测试订单流程 */ public function testOrderProcess() { $order = Event::fakeFor(function () { $order = factory(Order::class)->create(); Event::assertDispatched(OrderCreated::class); return $order; }); // 事件按正常方式发送,观察者将运行... $order->update([...]); } }
위 프로세스를 보다 편리하게 만들기 위해 Laravel의 기본 테스트 케이스 클래스를 사용하여mock
을 제공할 수 있습니다. 방법:<?php namespace Tests\Feature; use Tests\TestCase;use App\Mail\OrderShipped; use Illuminate\Support\Facades\Mail; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithoutMiddleware; class ExampleTest extends TestCase{ public function testOrderShipping() { Mail::fake(); // 断言没有发送任何邮件... 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('...'); }); // 断言邮件被发送两次... Mail::assertSent(OrderShipped::class, 2); // 断言没有发送邮件... Mail::assertNotSent(AnotherMailable::class); } }
작업 시뮬레이션🎜🎜시뮬레이션의 대안으로를 사용할 수 있습니다. Bus
Facade의fake
메소드는 작업이 실제로 실행을 위해 배포되는 것을 방지합니다. 가짜를 사용하는 경우 일반적으로 테스트 코드 뒤에 어설션이 나타납니다. 모의 대신Event
Facade의Fake
메서드를 사용하여 이벤트 리스너를 시뮬레이션할 수 있습니다. 이벤트 리스너는 테스트 중에 실제로 트리거되지 않습니다. 그런 다음 실행 중인 어설션 이벤트를 테스트하고 수신된 데이터를 검사할 수도 있습니다. fake를 사용하는 경우 일반적으로 테스트 코드 뒤에 어설션이 나타납니다. 🎜Mail::assertQueued(...); Mail::assertNotQueued(...);
🎜{note}
Event::fake()
를 호출한 후에는 이벤트 모니터링이 실행되지 않습니다. 따라서 이벤트 기반 테스트에서는 팩토리 모델을 사용해야 합니다. 예를 들어 모델의creating
이벤트에서 UUID를 생성하려면Event::fake()
를 호출해야 합니다. Strong> 이후 공장 모델을 사용합니다. 🎜🎜이벤트 하위 집합 시뮬레이션
🎜특정 이벤트 집합에 대한 이벤트 리스너만 시뮬레이션하려는 경우,fake
또는fakeFor
메소드로 전달될 수 있습니다: 🎜<?php namespace Tests\Feature; use Tests\TestCase; use App\Notifications\OrderShipped; use Illuminate\Support\Facades\Notification; use Illuminate\Notifications\AnonymousNotifiable; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithoutMiddleware; class ExampleTest extends TestCase{ public function testOrderShipping() { Notification::fake(); // 断言没有发送通知... 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 ); } }
🎜🎜🎜🎜범위가 지정된 이벤트 시뮬레이션
🎜테스트의 일부에 대해서만 이벤트 수신을 시뮬레이션하려는 경우fakeFor
메서드를 사용할 수 있습니다. 🎜<?php namespace Tests\Feature; use Tests\TestCase;use App\Jobs\ShipOrder; use Illuminate\Support\Facades\Queue; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithoutMiddleware; 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 ]); } }
🎜🎜🎜🎜🎜🎜메일 시뮬레이션
Mail
Facade의fake
메소드를 사용하여 이메일 전송을 시뮬레이션할 수 있습니다. 이메일은 테스트 중에 실제로 전송되지 않으며 그런 다음 주장할 수 있습니다. 사용자에게 메일이 전송되었다는 사실을 사용자가 수신한 내용까지 확인할 수 있습니다. 가짜를 사용할 때 어설션은 일반적으로 테스트 코드 뒤에 배치됩니다.Mail
Facade 的fake
方法来模拟邮件发送,测试时不会真的发送邮件,然后你可以断言 mailables 发送给了用户,甚至可以检查他们收到的内容。使用 fakes 时,断言一般放在测试代码的后面:<?php namespace Tests\Feature; use Tests\TestCase; use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\Storage; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithoutMiddleware; class ExampleTest extends TestCase{ public function testAvatarUpload() { Storage::fake('avatars'); $response = $this->json('POST', '/avatar', [ 'avatar' => UploadedFile::fake()->image('avatar.jpg') ]); // 断言文件已存储... Storage::disk('avatars')->assertExists('avatar.jpg'); // 断言文件不存在... Storage::disk('avatars')->assertMissing('missing.jpg'); } }
如果你用后台任务执行邮件发送队列,你应该是用
assertQueued
代替assertSent
:<?php namespace App\Http\Controllers; use Illuminate\Support\Facades\Cache; class UserController extends Controller{ /** * 显示应用里所有用户 * * @return Response */ public function index() { $value = Cache::get('key'); // } }
通知模拟
你可以使用
Notification
Facade 的fake
方法来模拟通知的发送,测试时并不会真的发出通知。然后你可以断言 notifications 发送给了用户,甚至可以检查他们收到的内容。使用 fakes 时,断言一般放在测试代码后面:<?php namespace Tests\Feature; use Tests\TestCase; use Illuminate\Support\Facades\Cache; use Illuminate\Foundation\Testing\RefreshDatabase; use Illuminate\Foundation\Testing\WithoutMiddleware; class UserControllerTest extends TestCase{ public function testGetIndex() { Cache::shouldReceive('get') ->once() ->with('key') ->andReturn('value'); $response = $this->get('/users'); // ... } }
队列模拟
作为模拟替代方案,你可以使用
rrreeeQueue
Facade 的fake
方法避免把任务真的放到队列中执行。然后你就可以断言任务已经被推送入队列了,甚至可以检查它们收到的数据。使用 fakes 时,断言一般放在测试代码的后面:存储模拟
你可以使用
rrreeeStorage
Facade 的fake
方法,轻松的生成一个模拟磁盘,结合 UploadedFile 类的文件生成工具,极大的简化了文件上传测试。例如:
rrreee{tip} 默认情况下,
백그라운드 작업을 사용하여 이메일 전송 대기열을 실행하는 경우fake
rrreeeassertSent
대신assertQueued
를 사용해야 합니다. :알림 시뮬레이션🎜알림
Facade를 사용할 수 있습니다. 알림 전송을 시뮬레이션하는가짜
메소드는 테스트 중에 실제로 알림이 전송되지 않습니다. 그런 다음 사용자에게 알림이 전송되었는지 확인하고 수신된 내용을 검사할 수도 있습니다. 가짜를 사용할 때 어설션은 일반적으로 테스트 코드 뒤에 배치됩니다. 시뮬레이션 또는Queue
Facade의fake
메서드를 사용하여 실제로 실행을 위해 작업을 대기열에 넣는 것을 방지할 수 있습니다. 그런 다음 작업이 대기열에 푸시되었는지 확인하고 수신된 데이터를 검사할 수도 있습니다. 가짜를 사용할 때 어설션은 일반적으로 테스트 코드 뒤에 배치됩니다. 🎜rrreee🎜🎜🎜🎜🎜storage Simulation🎜🎜you웹사이트에 처음 게시되었습니다. 🎜🎜Storage
Facade의fake
메소드를 사용하여 시뮬레이션된 디스크를 쉽게 생성할 수 있으며 UploadedFile 클래스의 파일 생성 도구와 결합되어 파일 업로드 테스트가 크게 단순화됩니다. 예: 🎜rrreee🎜{tip} 기본적으로
fake
메서드는 임시 디렉터리의 모든 파일을 삭제합니다. 이러한 파일을 유지하려면 "perciousFake"를 사용할 수 있습니다. 🎜🎜🎜🎜🎜🎜🎜🎜Facades
기존의 정적 메서드 호출과 달리 Facade는 목킹될 수도 있습니다. 기존의 정적 방법에 비해 의존성 주입을 사용해도 테스트 가능성이 절반도 떨어지지 않는 장점이 있습니다. 테스트에서 컨트롤러의 Laravel Facade에 대한 호출을 시뮬레이션할 수 있습니다. 예를 들어 다음 컨트롤러의 동작은 다음과 같습니다.
rrreeeshouldReceive
메서드를 통해Cache
Facade를 시뮬레이션할 수 있습니다. 이 함수는 MockeryshouldReceive
方法来模拟Cache
Facade,此函数会返回一个 Mockery 实例。由于 Facade 的调用实际是由 Laravel 的 服务容器 管理的,所以 Facade 能比传统的静态类表现出更好的可测试性。下面,让我们模拟一下Cache
Facade 的get
方法:{note} 你不能模拟
rrreee{note}Request
Facade 。相反,在运行测试时如果需要传入指定参数,请使用 HTTP 辅助函数,比如get
和post
。同理,请在测试时通过调用Config::set
来模拟Config
인스턴스. Facade 호출은 실제로 Laravel의 서비스 컨테이너에 의해 관리되기 때문에 Facade는 기존 정적 클래스보다 더 나은 테스트 가능성을 보여줄 수 있습니다. 다음으로,Cache
Facade의get
메소드를 시뮬레이션해 보겠습니다.Request
Facade는 시뮬레이션할 수 없습니다. 대신, 테스트를 실행할 때 특정 매개변수를 전달해야 하는 경우get
및post
와 같은 HTTP 도우미 함수를 사용하세요. 마찬가지로, 테스트 중에Config::set
를 호출하여Config
Facade를 시뮬레이션하세요. LearnKu.com