2016-03-18 24 views
6

イベントをテストしようとしていて、昨日働いていました。これは、テストコードをリファクタリングして、繰り返しすぎることを防ぐ前です。私は、ModelFactoriesを使って偽のデータを生成するsetUpメソッド呼び出しを追加しました。これは昨日の各テストケースで行われ、それが動作していたと言われています。Laravel 5.2イベントテスト:イベントが発生してもイベントが発生していないことを期待しているイベント

私は、setUpメソッドを使用することと関係があると思っていますが、なぜそうであるのかわかりません。最初に、ユニットテストの実行時に一度だけ実行されるので、setUpBeforeClass()静的メソッドを使用しようとしました。しかし、laravelアプリケーションはsetUp()の最初の呼び出しまで実際にはセットアップされていません...おそらくバグはありますか?これは、このポストSetting up PHPUnit tests in Laravelに記載されています。

したがってsetUpメソッドを使用し、staticプロパティがnullかどうかを確認しました。ヌルであればデータを生成します。ここで

ここでプロジェクトに

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

をPHPUnitの実行からの出力は、私が作成したユニットテストファイルのための私のコードです。

<?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/blob/master/tests/acceptance/scenarios/consulting/ConsultingScenarioTest.php))。また、[laravel documentation](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

あなたは(トレイトIlluminate/Foundation/Testing/Concerns/MocksApplicationServices内側)expectsEventsのソースコードを見れば、あなたはそれがすべて将来イベントを抑制し、収集し、アプリケーションのイベントディスパッチャを皮肉っ機能withoutEventsを、呼び出すことがわかります。

この時点でsetUp関数が既に呼び出されているため、イベントはテストで捕捉されずに記録され、アサーションが評価されたときには表示されません。

イベントが正しく表示されるようにするには、の前にアサーションが宣言されていることを確認してください。

関連する問題