2016-03-18 24 views
6

我一直在試着測試事件,並且我昨天已經開始工作。那是在我開始重構測試代碼以防止它過於重複之前。我添加了setUp方法調用來使用ModelFactories生成假數據。這在每個測試案例中都是在昨天完成的,正如它所說的那樣。Laravel 5.2事件測試:預計事件不會觸發事件,雖然它正在被解僱

我想這與使用setUp方法有關,但我不知道爲什麼會這樣。首先,我嘗試使用setUpBeforeClass()靜態方法,因爲它只在單元測試運行時運行一次。然而,laravel應用程序實際上並沒有設置,直到第一次調用setUp()...可能的錯誤可能是?它在此SO帖子Setting up PHPUnit tests in Laravel中有記錄。

因此我選擇使用setUp方法,只檢查靜態屬性是否爲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)); 
    }); 
} 
+0

我不確定靜態屬性(不判斷,我只是做不同的事情,[示例](https:// github。COM/timegridio/timegrid /斑點/主/測試/接受/場景/諮詢/ ConsultingScenarioTest.php))。此外,根據[laravel文檔](https://laravel.com/docs/master/testing)我認爲你不應該傳遞一個數組作爲參數,而是** Event **本身:'$ this-> expectsEvents(' \ App \ Events \ GroupMediaSaving');'或'$ this-> expectsEvents(App \ Events \ GroupMediaSaving :: class);' – alariva

+0

好的,檢查。你可以傳遞一個數組作爲參數。但是,您的活動課程路徑是否正確?在PHP> = 5.5中,您可以執行'$ this-> expectsEvents(App \ Events \ GroupMediaSaving :: class);',將讓您知道路徑是否無效。 – alariva

+0

不,我已經檢查過路徑,它們都適合我的事件並映射到實際的類。 –

回答

1

同樣的事情發生在我身上,$this->expectsEvent()沒有檢測到事件被解僱或防止它傳播到事件偵聽器..

以前,我是用Event::fire(new Event())我的射擊事件。我試圖將其更改爲event(new Event()),現在測試突然正常工作,它檢測到事件已被觸發並使事件沉默。

+0

同樣的事情發生在我身上。使用'Event :: fire()'導致測試失敗,但使用'event()'通過 – Jack

4

如果你看一下expectsEvents的源代碼(性狀Illuminate/Foundation/Testing/Concerns/MocksApplicationServices內),你會看到,它調用函數withoutEvents,它嘲笑應用程序事件調度,抑制和收集所有未來事件。

對於你來說問題在於setUp函數此時已經被調用,所以你的事件不會被測試捕獲和記錄,並且在斷言評估時不會顯示出來。

爲了正確看到事件觸發,您應該確保您在觸發事件的代碼之前聲明之前的代碼