2016-03-28 8 views
2

Varsayılan TestCase.php dosyası ile temel PHPUnit config dosyasını kullanıyorum.Bir olayın kaç kez ateşlendiğini test etmek Laravel yolu var mı?

Test sırasında bir etkinliğin birden çok kez tetiklenip tetiklenmediğini kontrol etmenin bir yolunu arıyorum. İdeal

function test_fires_multiple_events() 
{ 
    $this->expectsEvents(SomeEvent::class); 
} 

, ben isteyeyim:

function test_fires_multiple_events() 
{ 
    $this->expectsEvents(SomeEvent::class)->times(3); 
} 

cevap

2

MocksApplicationServices'daki koddan geçtikten sonra, bu özelliği ve withoutEvents() yöntemini yakaladığı alanları yakalayabildim.

function test_fires_multiple_events() 
{ 
    $this->withoutEvents(); // From MocksApplicationServices 

    $c = collect($this->firedEvents) 
       ->groupBy(function($item, $key) { return get_class($item); }) 
       ->map(function($item, $key) { return $item->count(); }); 

    $this->assertsEqual(3, $c->get(SomeEvent::class)); 

} 

neyi koleksiyon yapıyor adım adım için::

uzatma gibi görünecektir

1) collect($this->firedEvents): bir koleksiyon yakalanan olayları ve depolar onları götürür. Not etmek önemlidir ki, MocksApplicationServices her bir olayı bir diziye iter, yani saymaya devam ediyor.

2) groupBy(function($item, $key) { return get_class($item); }): Sınıf ismine göre gruplar, şimdi dizilerden oluşan bir koleksiyona sahibiz.

3) map(function($item, $key) { .. }: Sadece çocukları tazeleyin. Sadece biraz bunu temizlemek için

Illuminate\Support\Collection (1) (
    protected items -> array (2) [ 
     'App\Events\SomeEvent' => integer 2 
     'App\Events\SomeOtherEvent' => integer 1 
    ] 
) 

Düzenleme - Eğer baz testi Dava dosyasında aşağıdakileri ekleyebilirsiniz:

Bu gibi bir yapı ile sonuçlanan

public function assertEventFiredTimes($event, $count) 
{ 
    $this->assertEquals(
     count(collect($this->firedEvents) 
      ->groupBy(function($item, $key) { return get_class($item); }) 
      ->get($event, [])), 
     $count 
    ); 
} 

Ve Daha sonra testlerinizde:

$this->assertEventFiredTimes(SomeEvent::class, 3); 

withoutEvents() eklemeyi unutma.

+0

Harika bir yöntem ve zarif bir çözüm, sadece bir şey: Bazen firedEvents dizisi hem dizeleri hem de nesneler olaylarını ("kernel.handled" veya "locale.changed" gibi) içerebilir. Yani kullanmak isteyebilirsiniz: {return is_string ($ item)? $ item: get_class ($ item); } groupBy işlevinde herhangi bir olay türü ile çalışabilir. – kerwan

1

ben gibi bir şey yapabileceğini böylece o zaman alay size sınıf olay memuru enjekte etmek gerek:

Güncel kod benziyor laracasts içinde
$dispatcher->shouldReceive('fire')->with(SomeEvent::class)->times(3); 
2

Birisi bu aynı sorunla karşı karşıya ve çözüm buldu: https://laracasts.com/discuss/channels/general-discussion/testing-class-based-events-in-laravel-5

Temel olarak: kullandığınız etkinlik sınıfını beklemek için yalnızca Olay dağıtıcıyla dalga geçmeniz gerekir. Bundan sonra ihtiyacınız olan her şeyi kontrol edebilirsiniz.

+1

Linke minnettarım - ve şimdi bunun üzerinden okuma yapıyorum. Ancak yığın akışı genellikle cevabın çözümün çoğunluğunu içermesini tercih eder (gerekirse bir referans linki ile). Bu, gelecekteki ölü bağlantılardan kaçınmaktır. Yine de teşekkürler – Chris

İlgili konular