2016-03-18 11 views
6

Ich habe versucht, Ereignisse zu testen, und ich hatte es gestern funktioniert. Das war, bevor ich anfing, den Testcode umzuformatieren, damit er nicht zu wiederholend ist. Ich habe den Aufruf der Methode setUp hinzugefügt, um die gefälschten Daten mithilfe von ModelFactories zu generieren. Dies wurde gestern in jedem Testfall gemacht und wie gesagt funktionierte es.Laravel 5.2 Event Testing: expensesEvent das Ereignis nicht gefeuert, obwohl es gefeuert wird

Ich denke, es hat etwas mit der setUp-Methode zu tun, aber ich habe keine Ahnung, warum das der Fall wäre. Zuerst habe ich versucht, die statische Methode setUpBeforeClass() zu verwenden, da diese nur einmal bei Unit-Testläufen ausgeführt wird. Allerdings ist die Laravel-Anwendung erst beim ersten Aufruf von setUp() installiert ... Ein möglicher Fehler vielleicht? Es ist in diesem SO Post Setting up PHPUnit tests in Laravel dokumentiert.

Daher entschied ich mich, die setUp-Methode zu verwenden und einfach zu überprüfen, ob die statische Eigenschaft null ist oder nicht, wenn es null ist, dann generiert es die Daten, wenn es nicht einfach auf seinem Weg geht. Hier

ist die Ausgabe von laufenden phpunit an dem Projekt

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

Hier ist mein Code für die Unit-Test-Datei, die ich geschaffen habe.

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

Irgendwelche Gedanken, warum es die Ereignisse nicht gefeuert sieht? Ich finde es merkwürdig, dass sie gefeuert werden, wenn ich die Modelle innerhalb des Testfalls erstelle, aber innerhalb von setUp() scheitern scheint. Der schlimmste Teil ist, dass ich das GroupMedia-Modell nicht in der setUp-Methode erzeuge, sondern im Testfall.

Ich habe auch die Daten, die von der getRandomCommunityWithAssociatedData-Methode zurückgegeben wird, und es gibt ordnungsgemäße Modellobjekte alle mit ID-Attribute zurück, die mir sagt, dass sie alle in der Datenbank während der Erstellung gespeichert wurden.

Wie hier angefordert ist der Code, der tatsächlich das Ereignis auslöst, es befindet sich im GroupMedia-Modell in der statischen Boot-Methode.

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

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

Ich bin nicht sicher über die statischen Attribute (nicht zu urteilen, ich mache es einfach anders, [Beispiel] (https: // github.com/timegridio/timegrid/blob/Master/Tests/Akzeptanz/Szenarien/Beratung/ConsultingScenarioTest.php)). Laut der [laravel-Dokumentation] (https://laravel.com/docs/master/testing) sollten Sie kein Array als Argument übergeben, sondern das ** Event ** selbst: '$ this-> expectSevents (' \ App \ Events \ GroupMediaSaving '); 'oder' $ this-> expensesEvents (App \ Events \ GroupMediaSaving :: class); ' – alariva

+0

Ok, aktiviert. Sie können ein Array als Argument übergeben. Aber ist auch Ihr Ereignisklassenpfad korrekt? In PHP> = 5.5 können Sie '$ this-> expensesEvents (App \ Events \ GroupMediaSaving :: class);' ausführen, damit Sie wissen, ob der Pfad ungültig ist. – alariva

+0

Nein, ich habe die Pfade überprüft, sie sind alle für meine Events geeignet und entsprechen den tatsächlichen Klassen. –

Antwort

1

Gleiche passierte mir, $this->expectsEvent() wurde nicht erfasst wird, dass das Ereignis ausgelöst wurde oder es verhindern zu den Ereignis-Listener ausbreitet ..

Zuvor ich meine Ereignisse feuerte mit Event::fire(new Event()). Ich habe versucht, es zu event(new Event()) zu ändern, und der Test funktioniert jetzt plötzlich richtig, mit der Feststellung, dass das Ereignis ausgelöst wurde und das Ereignis stumm geschaltet wurde.

+0

Das gleiche ist mir passiert. Die Verwendung von 'Event :: fire()' führte dazu, dass der Test fehlschlug, aber 'event()' passierte – Jack

4

Wenn Sie expectsEvents auf den Quellcode schauen (im Zug Illuminate/Foundation/Testing/Concerns/MocksApplicationServices), werden Sie sehen, dass es die Funktion aufruft withoutEvents, die die Anwendung der Ereignis-Dispatcher spottet, zu unterdrücken und das Sammeln alle Zukunft Veranstaltungen.

Das Problem für Sie ist, dass die setUp Funktion bereits an diesem Punkt aufgerufen wurde, so dass Ihre Ereignisse nicht durch den Test abgefangen und protokolliert werden und nicht angezeigt werden, wenn die Assertion ausgewertet wird.

Um die Ereignisauslösung korrekt anzuzeigen, sollten Sie sicherstellen, dass Sie die Assertion vor den Code deklarieren, der die Ereignisse auslöst.

Verwandte Themen