Frage

Ich habe durch die verschiedenen Fragen auf Unit-Tests gesucht, aber kann man nicht finden, die speziell diese Frage beantwortet.

Ich habe mehrere PHP-Klassen bekam, die Funktionen enthalten, die wie folgt aussehen:

    static function _setSuspended($Suspended, $UserID)
    {
        try {
            $con = Propel::getConnection();

            $c1 = new Criteria();
            $c1->add(DomainsPeer::USERID,$UserID);

            $update = new Criteria();
            $update->add(DomainsPeer::SUSPENDED,$Suspended);

            BasePeer::doUpdate($c1, $update, $con);

            return true;
        } catch(PropelException $e) {
            return $e->getMessage();
        }
    }

Ich bin mit Propel als meine ORM. Ich habe verschiedene Unit-Tests Themen durchlesen, die über das Erstellen von ‚Mocks‘ und ‚Stubs‘ reden und was nicht, aber ich habe nicht in der Lage, etwas zu finden, die speziell sagen Ihnen, wie Sie eine Funktion wie oben zu testen.

Mein Denken geht in etwa so: Ich brauche die Funktion oben zu testen, damit ich mag es nennen. Aber wenn ich es nennen, es nutzt Propel als ORM und nach den Unit Testing Prinzipien soll ich jede Funktion selbst isolieren.

Ich sehe nicht, einen Weg, das zu tun. Was ich hier fehlt?

War es hilfreich?

Lösung

Ich habe festgestellt, dass die ORM verspotten mir nicht geben kein Vertrauen, weil die ORM-Konfiguration wird nie getestet. ORMs auch in einem Abstand Effekte viel Action haben, die falsche Vertrauen mit Unit-Tests geben kann. Mocking den Datenbanktreiber oder eine alternative Bereitstellung von In-Memory-Datenbank mir viel höheres Vertrauen gibt mein Code korrekt ist, und ist etwa so schwer wie die ORM spöttisch.

SQLite ist eine große In-Memory-Datenbank für Unit-Tests. Es ist auf der PDO-Datenbankliste unterstützt. (PDO ist die Propel 1.3-Datenbanktreiber.) Wenn Sie möchten, um eine In-Memory-Datenbank nicht verwenden, Sie möglicherweise in der Lage einen PDO Mock finden bereits geschrieben.

Andere Tipps

Das ist eine allgemeine Antwort, dass ich überhaupt nicht vertraut mit Propel bin und nur etwas besser vertraut mit PHP. Die grundlegende Antwort ist, dass Sie Dependency Injection verwenden. Statt direkt auf Ihrem ORM Bezug genommen wird, erstellen Sie einen Wrapper um ihn herum, spritzen dann die Hülle in Ihrer Klasse / Funktion tatsächlich zu nutzen. Zu tun Unit-Tests, dann erstellen Sie ein Modell oder gefälschte Version des Wrapper, der nicht auf die ORM ist eine Schnittstelle, sondern können Sie die Antworten von dem Wrapper auf Ihre Methode Anrufungen konfigurieren. Dadurch können Sie die ORM ausklammern, wenn das Gerät Ihre Funktionen zu testen.

Ich habe versucht, das gleiche Problem zu bewältigen, während eine PHPUnit-Plugin für Symfony . Ich landete es ähnlich wie Djangos Test-Framework nähern -. verwenden eine separate Datenbank / Verbindung, und zerstören und wieder aufbauen vor jedem Test

Ich fand, dass ich auch in der Lage war wegzukommen nur die Testdatenbank vor dem ersten Test in einem Testlauf Wiederaufbau (oder wenn ein Test weist er ausdrücklich auf); vor den anderen Tests, löscht sie einfach alle Daten der Dinge ein wenig zu beschleunigen.

Ich habe gelesen Misko Hevery Blog über das Testen viel in letzter Zeit. Es deckt diese Situation; Sie bräuchten DI (Dependency Injection) verwenden.

Ich kämpfe mich mit dieser ein wenig als gut, und ich auch propel verwenden.

Zum einen könnte man die „Suspend“ Methode zum „Objekt“ Klasse bewegen, anstatt der Peer. Für diese spezielle Funktion wie auch immer, müssen Sie nicht die statischen Methoden verwenden, um dies zu erreichen. Ihre API aussehen könnte:

MyObjectPeer::retrieveByPK(1)->suspend();

Dies würde über normale Einheit Testverfahren überprüfbar sein.

Wenn es wirklich die Datenbank, die getestet werden muss, dann AFAIK müssen Sie haben tatsächlich die DB in den Test einbezogen. Ich verwende ltree und PostGIS viel in meinem aktuellen Projekt, und ich kann nicht glauben, der auf andere Weise Unit-Tests für das Modell Logik ausführen, die auf dem DB andere abhängig, als es in meinen Tests einzubeziehen.

Dies ist ein exemple einer Klasse mit harter Abhängigkeit, die das Gerät nicht prüfbar sein kann.

Wir könnten die Lage sein, mit einer Verbindung zu einer anderen Datenbank zu testen, aber dann, es ist kein Unit Test mehr, sondern ein Integrationstest.

Die bessere Alternative, die ich denke über eine QueryFactory Klasse haben, ist, dass alle die verschiedenen Methoden wickeln, die Sie brauchen, und dann werden Sie es lustig zu machen können.

Zuerst im ersten erstelle ich eine Schnittstelle

interface iQueryFactory
{
    function firstFunction($argument);
    function secondFunction($argument, $argument2);
}

Die QueryFactory mit allen ORM Anfrage brauchen wir

class QueryFactory implements iQueryFactory
{
    function firstFunction($argument) 
    {
        // ORM thing
    }

    function secondFunction($argument, $argument2)
    {
        // ORM stuff
    }
}

Es ist das Geschäft Logique mit der Injektion der Abfrage Fabrik

class BusinessLogic 
{
    protected $queryFactory;

    function __construct($queryFactoryInjection) 
    {
        $this->queryFactory= $queryFactoryInjection;
    }

    function yourFunctionInYourBusinessLogique($argument, $argument2) 
    {
        // business logique

        try {
            $this->queryFactory->secondFunction($argument, $argument2);
        } catch (\Exception $e) {
            // log
            // return thing
        }

        // return stuff
    }
}

Der Mock Teil, beachten Sie, dass ich nicht ein Mock Rahmen für meine exemple verwenden (btw können Sie eine Antwort Setter erstellen)

class QueryFactoryMock implements iQueryFactory
{
    function firstFunction($argument) 
    {
        if (is_null($argument)) 
        {
            throw new \Exception("");
        } 
        else 
        {
            return "succes";
        }
    }

    function firstFunction($argument, $argument2) 
    { 
        // sutff  
    }
}

Dann endlich die Unit-Tests, die unsere Business-Logik mit dem Modell Implementierung testen

class BusinessLogicTest extends PHPUnit_Framework_TestCase 
{
    public function setUp() 
    {
        require_once "BusinessLogic.php";
    }

    public function testFirstFunction_WhenInsertGoodName() 
    {
        $queryMockup = new QueryFactoryMock();
        $businessLogicObject = new BusinessLogic($queryMockup);
        $response = $businessLogicObject ->firstFunction("fabien");

        $this->assertEquals($response, "succes");
    }

    public function testFirstFunction_WhenInsetNull() 
    {
        $queryMockup = new QueryFactoryMock();
        $businessLogicObject = new BusinessLogic($queryMockup);
        $response = $businessLogicObject->firstFunction(null);

        $this->assertEquals($response, "fail");
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top