2016-03-18 12 views
6

Ho cercato di testare gli eventi e l'ho fatto funzionare ieri. È stato prima che iniziassi a rifattare il codice di test per evitare che diventasse troppo ripetitivo. Ho aggiunto la chiamata al metodo setUp per generare i dati falsi usando ModelFactories. Questo è stato fatto in ogni caso di test di ieri e come dichiarato funzionava.Laravel 5.2 Test evento: attende che l'evento non venga attivato anche se è stato attivato

Sto pensando che abbia qualcosa a che fare con l'utilizzo del metodo setUp ma non ho idea del perché sia ​​così. Per prima cosa ho tentato di utilizzare il metodo statico setUpBeforeClass() poiché viene eseguito una sola volta durante le esecuzioni di test delle unità. Tuttavia l'applicazione laravel non è in realtà impostata fino alla prima chiamata a setUp() ... Un possibile bug forse? È documentato in questo post SO Setting up PHPUnit tests in Laravel.

Pertanto ho optato per utilizzare il metodo setUp e solo per verificare se la proprietà statica è nullo o no, se è nullo quindi genera i dati, se non si va semplicemente in questo modo.

Ecco l'output da PHPUnit in esecuzione sul progetto

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

Ecco il mio codice per il file di test di unità che ho creato.

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

Qualche idea sul motivo per cui non vede gli eventi che vengono generati? Trovo strano che siano licenziati se creo i modelli all'interno del test case ma sembra che stiano fallendo quando vengono eseguiti all'interno di setUp(). La parte peggiore è che non sto creando il modello GroupMedia nel metodo setUp piuttosto che nel caso di test.

Ho anche scaricato i dati che vengono restituiti dal metodo getRandomCommunityWithAssociatedData e restituisce gli oggetti modello corretti tutti con gli attributi id che mi dicono che sono stati tutti salvati nel database durante la creazione.

Come richiesto qui è il codice che sta effettivamente attivando l'evento, si trova nel modello GroupMedia nel metodo di avvio statico.

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

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

Non sono sicuro degli attributi statici (non giudicare, lo faccio solo in modo diverso, [esempio] (https: // github.com/timegridio/timegrid/blob/master/test/accettazione/scenari/consulenza/ConsultingScenarioTest.php)). Inoltre, come da [documentazione di laravel] (https://laravel.com/docs/master/testing) penso che non dovresti passare un array come argomento ma il ** Event ** stesso: '$ this-> expectsEvents (' \ App \ Events \ GroupMediaSaving '); 'o' $ this-> expectsEvents (App \ Events \ GroupMediaSaving :: class); ' – alariva

+0

Ok, selezionato. È possibile passare un array come argomento. Ma anche, il percorso della tua classe di eventi è corretto? In PHP> = 5.5 puoi fare '$ this-> expectsEvents (App \ Events \ GroupMediaSaving :: class);', ti farà sapere se il percorso non è valido. – alariva

+0

No, ho controllato i percorsi, sono tutti appropriati per i miei eventi e mappano le classi reali. –

risposta

1

Stessa cosa è successo a me, non era $this->expectsEvent() rilevare che l'evento era stato licenziato o evitare che si propaghino agli ascoltatori di eventi ..

precedenza, ho lanciavo le mie eventi utilizzando Event::fire(new Event()). Ho provato a cambiarlo in event(new Event()) e il test improvvisamente funziona correttamente ora, rilevando che l'evento è stato attivato e silenziato l'evento.

+0

La stessa cosa è successa a me. L'uso di 'Event :: fire()' ha causato il fallimento del test ma l'utilizzo di 'event()' passaggi – Jack

4

Se si guarda il codice sorgente per expectsEvents (all'interno del tratto Illuminate/Foundation/Testing/Concerns/MocksApplicationServices), vedrete che si chiama la funzione withoutEvents, che prende in giro il dispatcher di eventi di applicazione, la soppressione e la raccolta di tutti i futuri eventi.

Il problema per voi è che la funzione setUp sarà già stata chiamata a questo punto, quindi gli eventi non verranno rilevati e registrati dal test e non verranno visualizzati quando viene valutata l'asserzione.

Per visualizzare correttamente lo sparo degli eventi, è necessario assicurarsi di dichiarare l'asserzione prima del il codice che attiva gli eventi.

Problemi correlati