2017-06-30 5 views
0
<?php 

use yii\db\ActiveRecord; 

class Model extends ActiveRecord 
{ 
    protected static $ids = []; 

    public static function getIds() 
    { 
     if (empty(static::$ids)) { 
      static::$ids = static::find()->select('id')->column(); 
     } 

     return static::$ids; 
    } 
} 

Wie wird der Test verwendet, um sicherzustellen, dass die Abfrage einmal durch wiederholtes Aufrufen dieser Methode ausgeführt wird?Wie testet man eine Methode, die die Cache-Variable verwendet?

Vorzugsweise mit codeception oder phpunit.

+0

Rollback auf den Standardwert jedes Mal, wenn Sie das Modell wiederverwenden? – Yerke

Antwort

3

Mit Tests können Sie nicht nur sicherstellen, dass Ihr Code funktioniert, sondern auch Code-Gerüche identifizieren. In Ihrem Fall ist das Schreiben eines Tests schwierig, da Sie statische Methoden verwenden.

Früher gab es eine staticExpects Methode, aber das war in phpunit vor langer Zeit veraltet, so dass das nicht wirklich machbar ist. Die beste Möglichkeit, diesen Code testbar zu machen, besteht darin, das Schlüsselwort static zu entfernen. Dies ist einfach für getIds(), aber da die statische find() von einem Drittanbieter (Yii ActiveRecord) definiert ist, können Sie es nicht wirklich entfernen. Stattdessen könnten Sie es in eine nicht statische Methode umbrechen. Dies bietet Ihnen den Vorteil, dass Sie sich in Zukunft vom Active Record zu einer anderen Implementierung wie Doctrine bewegen können, indem Sie einfach diese kleinen Methoden, die den 3rd-Party-Code umschließen, berühren.

Sobald Sie dies tun, können Sie einen Teil-Mock Ihres Modells erstellen, um sicherzustellen, dass Methode aufgerufen wird:

class Model extends ActiveRecord 
{ 
    private $ids; 

    protected function findIds() 
    { 
     return static::find()->select('id')->column(); 
    } 

    public function getIds() 
    { 
     if (empty($this->ids)) { 
      $this->ids = $this->findIds() 
     } 

     return $this->ids; 
    } 
} 

und im Test:

public function testFindIdsIsCalledWhenGetterIsNotInitialized() 
{ 
    $model = $this->getMockBuilder(Model::class) 
     ->setMethods(['findIds']) 
     ->getMock(); 
    $model->expects($this->once()) 
     ->method('findIds') 
     ->will($this->returnValue([1, 2, 3])); 

    $ids = $model->getIds(); 

    $this->assertEquals([1, 2, 3], $ids); 
} 

Dies sollte 2 Behauptungen haben, eine für den erwarteten Methodenaufruf und eine für die zurückgegebenen Werte. Dieser Test umgeht den Active Record und stellt nur sicher, dass Ihre getIds() Methode wie erwartet funktioniert. Eine andere Möglichkeit, dies zu erreichen, ist, wie in den Kommentaren zu Ihrer Frage erwähnt, die Verwendung eines Funktionstests, der die Datenbankinteraktionen tatsächlich testet, indem die Daten aus einer (Test-) Datenbank abgerufen werden. Offensichtlich erfordert dies eine Datenbankverbindung und das Abrufen von Testdaten, z. von einigen zuvor eingerichteten Fixtures ist es etwas mehr Arbeit und der Test wird langsamer. Abhängig davon, wie groß Ihr Projekt ist, ist das möglicherweise kein Problem, und Sie könnten sich auch beim Testen der Logik in der Active Record-Implementierung wohler fühlen.

Verwandte Themen