2013-07-02 14 views
7

ile çalışmaz:laravel 4 Modeli Olaylar Ben <code>creating</code> Modeli Olay ile laravel 4 örnek bir tarafında doğrulama inşa PHPUnit

class User extends Eloquent { 

    public function isValid() 
    { 
     return Validator::make($this->toArray(), array('name' => 'required'))->passes(); 
    } 

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

     static::creating(function($user) 
     { 
      echo "Hello"; 
      if (!$user->isValid()) return false; 
     }); 
    } 
} 

O iyi çalışıyor ama PHPUnit ile sorunları var. İki Aşağıdaki testler tam olarak aynıdır ama birincisi geçiş juste: Aynı testte iki kez bir kullanıcı oluşturmayı denerseniz

class UserTest extends TestCase { 

    public function testSaveUserWithoutName() 
    { 
     $count = User::all()->count(); 

     $user = new User; 
     $saving = $user->save(); 

     assertFalse($saving);      // pass 
     assertEquals($count, User::all()->count()); // pass 
    } 

    public function testSaveUserWithoutNameBis() 
    { 
     $count = User::all()->count(); 

     $user = new User; 
     $saving = $user->save(); 

     assertFalse($saving);      // fail 
     assertEquals($count, User::all()->count()); // fail, the user is created 
    } 
} 

, çalışıyor, ancak bağlanma olayı sadece mevcut ise gibidir Test sınıfımın ilk testi. İlk test yürütme sırasında echo "Hello"; sadece bir kez yazdırılır.

Sorumun için durum basitleştirmek ama sorunu görebilirsiniz: Farklı birim testlerinde çeşitli doğrulama kurallarını test edemez. Saatlerden beri neredeyse her şeyi deniyorum ama şimdi pencerelerden dışarı atlamak üzereyim! Herhangi bir fikir ?

+2

Oku https://github.com/laravel/framework/issues/1181 – crynobone

+2

Teşekkür ederim. Son olarak, Model Olaylar kolayca test edilemez. Sorunumu bu numarayla çözüyorum: 'setUp()' yönteminde 'Kullanıcı :: boot()' olarak adlandırıyorum. –

+1

Kullanıcı Kullanıcı gözlemini (yeni UserObserver) 'kullanmayı tercih ederim, bu şekilde' UserObserver'ı kendi başınıza test edebilirsiniz. – crynobone

cevap

3

Sorun Github'da belgelenmiştir. Yukarıdaki yorumları daha ayrıntılı olarak açıklayın.

otomatik olarak testler sırasında tüm model olaylarını sıfırlamak için Github içinde çözümler 'biri modifiye ettik. TestCase.php dosyanıza aşağıdakileri ekleyin.

app/test/TestCase.php

public function setUp() 
{ 
    parent::setUp(); 
    $this->resetEvents(); 
} 


private function resetEvents() 
{ 
    // Get all models in the Model directory 
    $pathToModels = '/app/models'; // <- Change this to your model directory 
    $files = File::files($pathToModels); 

    // Remove the directory name and the .php from the filename 
    $files = str_replace($pathToModels.'/', '', $files); 
    $files = str_replace('.php', '', $files); 

    // Remove "BaseModel" as we dont want to boot that moodel 
    if(($key = array_search('BaseModel', $files)) !== false) { 
     unset($files[$key]); 
    } 

    // Reset each model event listeners. 
    foreach ($files as $model) { 

     // Flush any existing listeners. 
     call_user_func(array($model, 'flushEventListeners')); 

     // Reregister them. 
     call_user_func(array($model, 'boot')); 
    } 
} 
+0

Sorunumu temel numaramdan daha genel bir şekilde çözüyor (her model için "Kullanıcı :: önyükleme()" gibi bir satır ekleyin) ancak iki nedenden dolayı beni şaşırtmamı sağlayın: bir sürü tuhaf kod ekleyelim TestCase sınıfı ve her testten önce dosyaları ayrıştırır (bu da performans sorunlarına neden olabilir) ... –

+0

Model ilk önce Model'i uzatıyorsa test etmeli, bazen flushEventListeners yöntemine sahip olmayabilir. – Benubird

0

Ben alt dizinlerinde mankenlerim yüzden @TheShiftExchange kodunu düzenledi var biraz

//Get all models in the Model directory 
$pathToModels = '/path/to/app/models'; 
$files = File::allFiles($pathToModels); 

foreach ($files as $file) { 
    $fileName = $file->getFileName(); 
    if (!ends_with($fileName, 'Search.php') && !starts_with($fileName, 'Base')) { 
     $model = str_replace('.php', '', $fileName); 
     // Flush any existing listeners. 
     call_user_func(array($model, 'flushEventListeners')); 
     // Re-register them. 
     call_user_func(array($model, 'boot')); 
    } 
}