Laravel 5.2 事件测试:expectsEvent 没有看到事件被触发,尽管它正在被触发
Laravel 5.2 Event Testing: expectsEvent not seeing the event fired although it is being fired
我一直在尝试测试事件,昨天我让它工作了。那是在我开始重构测试代码以防止它过于重复之前。我添加了 setUp 方法调用以使用 ModelFactories 生成假数据。这是昨天在每个测试用例中完成的,并且正如所声明的那样有效。
我认为这与使用 setUp 方法有关,但我不知道为什么会这样。首先,我尝试使用 setUpBeforeClass() 静态方法,因为它在单元测试 运行 中仅 运行 一次。然而,laravel 应用程序直到第一次调用 setUp() 时才真正设置...可能是一个错误?它记录在这个 SO post Setting up PHPUnit tests in Laravel.
因此我选择使用 setUp 方法,只检查静态 属性 是否为空,如果为空则生成数据,如果不是则继续进行。
这是项目运行ning phpunit 的输出
➜ project git:(laravel-5.2-testing) ✗ phpunit
PHPUnit 5.2.10 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 8.94 seconds, Memory: 33.50Mb
There was 1 error:
1) UserEmailNotificationsTest::testNotificationSentOnGroupMediaSaving
Exception: These expected events were not fired: [\App\Events\GroupMediaSaving]
/Users/jcrawford/Dropbox/Work/Viddler/Repositories/l5_media_communities/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MocksApplicationServices.php:44
/Users/jcrawford/Dropbox/Work/Viddler/Repositories/l5_media_communities/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:127
FAILURES!
Tests: 1, Assertions: 0, Errors: 1, Skipped: 8.
这是我创建的单元测试文件的代码。
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class UserEmailNotificationsTest extends \TestCase
{
use DatabaseTransactions;
const COMMUNITIES_TO_CREATE = 3;
const USERS_TO_CREATE = 10;
const ADMINS_TO_CREATE = 5;
protected static $communities = null;
protected static $users = null;
protected static $admins = null;
public function setUp()
{
parent::setUp(); // TODO: Change the autogenerated stub
if(is_null(self::$communities)) {
self::$communities = factory(\Community::class, self::COMMUNITIES_TO_CREATE)->create()->each(function ($community) {
self::$users[$community->id] = factory(User::class, self::USERS_TO_CREATE)->create()->each(function (\User $user) use ($community) {
$user->community()->associate($community);
$user->save();
});
self::$admins[$community->id] = factory(User::class, self::ADMINS_TO_CREATE, 'superadmin')->create()->each(function (\User $admin) use ($community) {
$admin->community()->associate($community);
$admin->save();
});
$community->save();
});
}
}
public static function getRandomCommunityWithAssociatedData()
{
$community = self::$communities[mt_rand(0, count(self::$communities)-1)];
return ['community' => $community, 'users' => self::$users[$community->id], 'admins' => self::$admins[$community->id]];
}
/**
* Test that the notification event is fired when a group media
* item is saved.
*/
public function testNotificationSentOnGroupMediaSaving()
{
$data = self::getRandomCommunityWithAssociatedData();
// FOR SOME REASON THIS SAYS THE EVENT IS NEVER FIRED WHEN IT ACTUALLY IS FIRED.
$this->expectsEvents(['\App\Events\GroupMediaSaving']);
$community = $data['community'];
$admin = $data['admins'][0];
$user = $data['users'][0];
$asset = factory(Asset\Video::class)->make();
$asset->community()->associate($community);
$asset->user()->associate($admin);
$asset->save();
$group = factory(Group::class)->make();
$group->community()->associate($community);
$group->created_by = $admin->id;
$group->save();
$groupMedia = factory(GroupMedia::class)->make();
$groupMedia->asset()->associate($asset);
$groupMedia->user()->associate($user);
$groupMedia->group()->associate($group);
$groupMedia->published_date = date('Y-m-d H:i:s', strtotime('-1 day'));
$groupMedia->save();
// I can print_r($groupMedia) here and it does have an ID attribute so it was saved, I also put some debugging in the event object and it is actually fired.....
}
}
关于为什么它看不到正在触发的事件有什么想法吗?我觉得奇怪的是,如果我在测试用例中创建模型但在 setUp()
中完成时似乎失败了,它们就会被解雇。最糟糕的部分是我没有在 setUp 方法中创建 GroupMedia 模型,而是在测试用例中完成。
我还转储了从 getRandomCommunityWithAssociatedData
方法返回的数据,它返回了正确的模型对象,所有这些对象都具有 id 属性,这告诉我它们在创建期间都已保存到数据库中。
此处要求的是实际触发事件的代码,它位于静态启动方法中的 GroupMedia 模型中。
protected static function boot()
{
parent::boot();
static::saving(function($groupMedia) {
Event::fire(new \App\Events\GroupMediaSaving($groupMedia));
});
}
如果您查看 expectsEvents
的源代码(在特征 Illuminate/Foundation/Testing/Concerns/MocksApplicationServices
内),您会看到它调用函数 withoutEvents
,它模拟应用程序事件调度程序,抑制和收集所有 future 事件。
你的问题是此时已经调用了 setUp
函数,所以你的事件不会被测试捕获和记录,也不会在评估断言时显示出来.
为了正确查看触发的事件,您应该确保在触发事件的代码之前声明断言。
同样的事情发生在我身上,$this->expectsEvent()
没有检测到事件正在被触发或阻止它传播到事件侦听器..
之前,我使用 Event::fire(new Event())
触发我的事件。我尝试将其更改为 event(new Event())
并且测试现在突然可以正常工作,它检测到事件已被触发并使事件静音。
我一直在尝试测试事件,昨天我让它工作了。那是在我开始重构测试代码以防止它过于重复之前。我添加了 setUp 方法调用以使用 ModelFactories 生成假数据。这是昨天在每个测试用例中完成的,并且正如所声明的那样有效。
我认为这与使用 setUp 方法有关,但我不知道为什么会这样。首先,我尝试使用 setUpBeforeClass() 静态方法,因为它在单元测试 运行 中仅 运行 一次。然而,laravel 应用程序直到第一次调用 setUp() 时才真正设置...可能是一个错误?它记录在这个 SO post Setting up PHPUnit tests in Laravel.
因此我选择使用 setUp 方法,只检查静态 属性 是否为空,如果为空则生成数据,如果不是则继续进行。
这是项目运行ning phpunit 的输出
➜ project git:(laravel-5.2-testing) ✗ phpunit
PHPUnit 5.2.10 by Sebastian Bergmann and contributors.
E 1 / 1 (100%)
Time: 8.94 seconds, Memory: 33.50Mb
There was 1 error:
1) UserEmailNotificationsTest::testNotificationSentOnGroupMediaSaving
Exception: These expected events were not fired: [\App\Events\GroupMediaSaving]
/Users/jcrawford/Dropbox/Work/Viddler/Repositories/l5_media_communities/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/MocksApplicationServices.php:44
/Users/jcrawford/Dropbox/Work/Viddler/Repositories/l5_media_communities/vendor/laravel/framework/src/Illuminate/Foundation/Testing/TestCase.php:127
FAILURES!
Tests: 1, Assertions: 0, Errors: 1, Skipped: 8.
这是我创建的单元测试文件的代码。
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class UserEmailNotificationsTest extends \TestCase
{
use DatabaseTransactions;
const COMMUNITIES_TO_CREATE = 3;
const USERS_TO_CREATE = 10;
const ADMINS_TO_CREATE = 5;
protected static $communities = null;
protected static $users = null;
protected static $admins = null;
public function setUp()
{
parent::setUp(); // TODO: Change the autogenerated stub
if(is_null(self::$communities)) {
self::$communities = factory(\Community::class, self::COMMUNITIES_TO_CREATE)->create()->each(function ($community) {
self::$users[$community->id] = factory(User::class, self::USERS_TO_CREATE)->create()->each(function (\User $user) use ($community) {
$user->community()->associate($community);
$user->save();
});
self::$admins[$community->id] = factory(User::class, self::ADMINS_TO_CREATE, 'superadmin')->create()->each(function (\User $admin) use ($community) {
$admin->community()->associate($community);
$admin->save();
});
$community->save();
});
}
}
public static function getRandomCommunityWithAssociatedData()
{
$community = self::$communities[mt_rand(0, count(self::$communities)-1)];
return ['community' => $community, 'users' => self::$users[$community->id], 'admins' => self::$admins[$community->id]];
}
/**
* Test that the notification event is fired when a group media
* item is saved.
*/
public function testNotificationSentOnGroupMediaSaving()
{
$data = self::getRandomCommunityWithAssociatedData();
// FOR SOME REASON THIS SAYS THE EVENT IS NEVER FIRED WHEN IT ACTUALLY IS FIRED.
$this->expectsEvents(['\App\Events\GroupMediaSaving']);
$community = $data['community'];
$admin = $data['admins'][0];
$user = $data['users'][0];
$asset = factory(Asset\Video::class)->make();
$asset->community()->associate($community);
$asset->user()->associate($admin);
$asset->save();
$group = factory(Group::class)->make();
$group->community()->associate($community);
$group->created_by = $admin->id;
$group->save();
$groupMedia = factory(GroupMedia::class)->make();
$groupMedia->asset()->associate($asset);
$groupMedia->user()->associate($user);
$groupMedia->group()->associate($group);
$groupMedia->published_date = date('Y-m-d H:i:s', strtotime('-1 day'));
$groupMedia->save();
// I can print_r($groupMedia) here and it does have an ID attribute so it was saved, I also put some debugging in the event object and it is actually fired.....
}
}
关于为什么它看不到正在触发的事件有什么想法吗?我觉得奇怪的是,如果我在测试用例中创建模型但在 setUp()
中完成时似乎失败了,它们就会被解雇。最糟糕的部分是我没有在 setUp 方法中创建 GroupMedia 模型,而是在测试用例中完成。
我还转储了从 getRandomCommunityWithAssociatedData
方法返回的数据,它返回了正确的模型对象,所有这些对象都具有 id 属性,这告诉我它们在创建期间都已保存到数据库中。
此处要求的是实际触发事件的代码,它位于静态启动方法中的 GroupMedia 模型中。
protected static function boot()
{
parent::boot();
static::saving(function($groupMedia) {
Event::fire(new \App\Events\GroupMediaSaving($groupMedia));
});
}
如果您查看 expectsEvents
的源代码(在特征 Illuminate/Foundation/Testing/Concerns/MocksApplicationServices
内),您会看到它调用函数 withoutEvents
,它模拟应用程序事件调度程序,抑制和收集所有 future 事件。
你的问题是此时已经调用了 setUp
函数,所以你的事件不会被测试捕获和记录,也不会在评估断言时显示出来.
为了正确查看触发的事件,您应该确保在触发事件的代码之前声明断言。
同样的事情发生在我身上,$this->expectsEvent()
没有检测到事件正在被触发或阻止它传播到事件侦听器..
之前,我使用 Event::fire(new Event())
触发我的事件。我尝试将其更改为 event(new Event())
并且测试现在突然可以正常工作,它检测到事件已被触发并使事件静音。