2014-06-16 6 views
6

Da wir jetzt bei mehreren Projekten mit Symfony 2 arbeiten, stellen wir fest, dass wir ziemlich viel Code unter unseren Projekten austauschen können. Also haben wir begonnen, Features in Symfony 2-Bundles zu extrahieren, um sie zwischen unseren Projekten zu teilen.So testen Sie ein freigegebenes Symfony 2 Bundle ohne ein ganzes Projekt

Während wir im Grunde Dinge arbeiten, gibt es noch einige Fragen, die nicht leicht zu googeln sind, besonders wenn es darum geht, das geteilte Paket zu testen.

Das erste kleine Bündel, das wir extrahiert haben, enthält eine Doktrinenentität, eine kernel.event_listener, die automatisch in den DI-Container des Clientprojekts eingefügt wird, eine Anmerkung, einen anderen Dienst und ein paar Befehle. Die Grundidee ist, dass das Client-Projekt seine Controller mit unserer Annotation annotieren kann, der event_listener Anfragen an die annotierten Controller abfängt und zusätzliche Logik (die die Doktrin-Entity involviert) ausführt, bevor der Controller schließlich aufgerufen wird. Die Befehle sollen Datenbankeinträge der Doktrinsentität verwalten.

Bis jetzt funktioniert alles genau so, wie wir es erwartet haben, aber wir kämpfen mit der Testbarkeit des Bündels allein. Zunächst einmal enthält das Git-Repository, das das Paket enthält, kein vollständiges Symfony2-Projekt. Das wäre übertrieben, da wir hier nur ein Bündel aufbauen, nicht eine ganze Anwendung, oder?

Aber wie können wir den Event Listener testen? Wie können wir testen, ob es in den DI-Container injiziert wird? Wir benötigen einen Test-Controller, der mit unserer speziellen Anmerkung kommentiert wird, damit wir testen können, ob unser Ereignis-Listener ihn korrekt erfasst. Dieser Controller muss immer nur beim Testen verfügbar sein und darf niemals in einer Client-Anwendung erscheinen.

Wie können wir die Befehle testen? Wir müssten die Datenbank hinter der Doktrin verspotten. Wenn wir versuchen, den Befehl in einem phpunit Test auszuführen, die mit /vendor/autoload.php einfach Bootstrap ist, natürlich erhalten wir:

Fatal error: Call to undefined method Symfony\Component\Console\Application::getKernel() in /.../vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Command/ContainerAwareCommand.php on line 3

So fühlt es sich wie wir Gonna am Ende brauchen eine ganze Symfony2 Projekt in unserem Bundle-Repository sowieso sind in um das gesamte Framework zu starten, um eventuell unsere Komponenten testen zu können. Als ich mir Open-Source-Symfony2-Bundles anschaute, fand ich keine, bei denen das gesamte Framework in ihre Git-Repos eingecheckt war, so dass es sich immer noch falsch anfühlt.

Was fehlt mir? Gibt es eine Dokumentation über Bundle-Only/Applicationless Bundle-Entwicklung, die ich vermisse?

Edit:

ich hier eine Lösung für den Befehl Test gefunden: http://www.ricardclau.com/2013/02/testing-symfony2-commands-mocking-the-di-container-with-mockery/

Es ist der Fehler von ContainerAwareCommand stellte sich heraus kam, einen neuen Container zu schaffen versuchen, die offensichtlich nicht in einem bloßen Testumgebung funktionieren würde . Ich löste das Problem, indem sie den Behälter spöttisch und in den Befehl manuell wie so Injektion:

use Symfony\Component\Console\Application; 
use Symfony\Component\Console\Tester\CommandTester; 

class MyCommandTest extends \PHPUnit_Framework_TestCase { 

    public function testExecute() { 
     $application = new Application(); 
     $application->add(new MyCommand()); 

     $command = $application->find('my:command'); 
     $command->setContainer($this->getMockContainer()); // <= This avoids ContainerAwareCommand creating a 'real' container in a test env 
     $commandTester = new CommandTester($command); 
     $commandTester->execute(array('command' => $command->getName())); 

     print $commandTester->getDisplay(); 

     $this->assertRegExp('/.../', $commandTester->getDisplay()); 
    } 

    protected function getMockContainer() { 
     // Mock the container and everything you'll need here 
     $mockDoctrine = $this->getMock('Symfony\Bridge\Doctrine\RegistryInterface'); 
     $mockDoctrine->...; 

     $mockContainer = $this->getMock('Symfony\Component\DependencyInjection\Container'); 
     $mockContainer->expects($this->once()) 
         ->method('get') 
         ->with('doctrine') 
         ->willReturn($mockDoctrine); 
     return $mockContainer; 
    } 
} 

ich die Controller-Tests erraten werden in einem ähnlichen, Mock-schwer, so zu arbeiten haben. Wenn ich eine Lösung dafür finde, werde ich hier eine vollständige Antwort posten ...

+0

Ich bin nicht wirklich ein Experte (nicht zu viel Zeit zu experimentieren und zu viel Arbeit), aber ich denke, dass Sie brauchen nur eine Teilmenge von Abhängigkeiten wie Framework-Bundle, Konsole, http-Kernel zum Einrichten und Ausführen Ihrer Tests. – gremo

+0

Vielleicht sollte Ihre Bearbeitung eine Antwort sein ... Wie auch immer, guter Ausgangspunkt. Vielen Dank! – Aerendir

Antwort

0

Diese Frage ist ziemlich alt, aber ich bin gerade darüber gestolpert.

Bundles sind eine Symfony-spezifische Möglichkeit, ganze Bibliotheken inkl. ihre jeweilige Abhängigkeitsinjektionsbehälterkonfiguration.

Daher hängen Bundles vom Symfony-Kernel ab und wenn ein Bundle von einem anderen Bundle abhängt, erzeugen Sie starke Abhängigkeiten, die Unit-Tests effektiv verhindern: Um eine Unit (eine Klasse) in Bundle A zu testen, benötigen Sie Bundle B plus der Symfony-Kernel.

Sie können zwar noch testen, aber die daraus resultierenden Tests sind Akzeptanz-/Integrationstests, keine Unit-Tests mehr. Diese sind nicht für testgetriebene Entwicklung geeignet, langsam und zerbrechlich, wie Sie bereits bemerkt haben.

aktualisieren

ich einen Blog-Post über das gerade geschrieben: https://lastzero.net/2015/11/dependent-symfony-2-bundles-and-testability/

Verwandte Themen