Laravel 5.2事件测试:尽管事件被触发,但expectedEvent看不到事件被触发 [英] Laravel 5.2 Event Testing: expectsEvent not seeing the event fired although it is being fired

查看:104
本文介绍了Laravel 5.2事件测试:尽管事件被触发,但expectedEvent看不到事件被触发的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在尝试测试事件,并且昨天它可以正常工作.那是在我开始重构测试代码以防止其过于重复之前.我添加了setUp方法调用,以使用ModelFactories生成假数据.昨天在每个测试用例中都完成了该操作,并指出它正在工作.

我认为这与使用setUp方法有关,但是我不知道为什么会这样.首先,我尝试使用setUpBeforeClass()静态方法,因为该方法仅在单元测试运行时运行一次.但是,laravel应用程序实际上是在第一次调用setUp()之前才安装的……可能是一个错误?在该SO帖子在Laravel中设置PHPUnit测试中对此进行了记录.. >

因此,我选择使用setUp方法,只是检查一下static属性是否为null,如果为null,那么它将生成数据,如果不是,则继续进行.

这是在项目上运行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));
    });
}

解决方案

我发生了同样的事情,$this->expectsEvent()并未检测到该事件被触发或无法传播到事件侦听器..

以前,我是使用Event::fire(new Event())触发事件的.我尝试将其更改为event(new Event()),现在该测试突然正常工作,它检测到该事件已被触发并使该事件静音.

I have been trying to test events and I had it working yesterday. That was before I started to refactor the test code to keep it from being too repetitious. I added the setUp method call to generate the fake data using ModelFactories. This was done in each test case yesterday and as stated it was working.

I am thinking it has something to do with using the setUp method but I have no idea why that would be the case. First I attempted to use setUpBeforeClass() static method as that is only run once on unit test runs. However the laravel application is not actually setup until the first call to setUp()... A possible bug maybe? It is documented in this SO post Setting up PHPUnit tests in Laravel.

Therefore I opted to use the setUp method and just check to see if the static property is null or not, if it is null then it generates the data, if not it just goes on it's way.

Here is the output from running phpunit on the project

➜  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.

Here is my code for the unit test file that I have created.

<?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.....
    }
}

Any thoughts as to why it doesn't see the events being fired? I find it odd that they are fired if I create the models inside the test case but seem to be failing when done inside of setUp(). The worst part is I am not creating the GroupMedia model in the setUp method rather that is done in the test case.

I have also dumped the data that is returned from the getRandomCommunityWithAssociatedData method and it is returning proper model objects all with id attributes which tells me they were all saved to the database during creation.

As requested here is the code that is actually firing the event, it is located in the GroupMedia model in the static boot method.

protected static function boot()
{
    parent::boot();

    static::saving(function($groupMedia) {
        Event::fire(new \App\Events\GroupMediaSaving($groupMedia));
    });
}

解决方案

Same thing happened to me, $this->expectsEvent() was not detecting that the event was being fired or prevent it from propagating to the event listeners..

Previously, I was firing my events using Event::fire(new Event()). I tried changing it to event(new Event()) and the test suddenly works correctly now, with it detecting that the event has been fired and silencing the event.

这篇关于Laravel 5.2事件测试:尽管事件被触发,但expectedEvent看不到事件被触发的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆