Automatische Injektion von Mocks in Testpersonen über #InjectMocks- und #Mock-Annotationen, um Unit-Tests mit PHPUnit zu beschleunigen.
Leia eine Version auf Portugiesisch hier.
Zur Installation in der Entwicklungsumgebung:
composer require --dev silasyudi/inject-mocks
Mithilfe der Annotationen #InjectMocks und #Mock in Testklassen können Sie Testpersonen automatisch Mocks injizieren.
In einem typischen Szenario würden wir es so machen:
class SomeTest extends PHPUnit Framework TestCase
{
public void testSomething()
{
$ someDependency = $ this -> createMock (Dependency::class);
$ anotherDependency = $ this -> createMock (AnotherDependency::class);
. . .
$ subject = new Service ( $ someDependency , $ anotherDependency , ...);
. . .
}
...
Dieser Ansatz bringt Schwierigkeiten bei der Wartung mit sich, denn wenn das Testsubjekt geändert wird, sei es durch Hinzufügen, Verringern oder Ersetzen der Abhängigkeiten, müssen Sie es in jedem Test ändern.
Mit den #InjectMocks/#Mock-Annotationen abstrahieren wir diese Testsubjektänderungen. Beispiel:
use SilasYudi InjectMocks InjectMocks ;
use SilasYudi InjectMocks Mock ;
use SilasYudi InjectMocks MockInjector ;
class SomeTest extends PHPUnit Framework TestCase
{
#[Mock]
private Dependency $ someDependency ;
#[Mock]
private AnotherDependency $ anotherDependency ;
. . .
# [InjectMocks]
public function setUp() : void
{
MockInjector:: inject ( $ this );
}
public void testSomething ()
{
// $this->subject e as dependências já estão instanciadas.
}
...
Wie im Beispiel im vorherigen Thema muss das Attribut #InjectMocks auf der Eigenschaft des Testsubjekts platziert werden, das Sie testen möchten, und das Attribut #Mock muss auf den Eigenschaften platziert werden, die den Abhängigkeiten entsprechen, die Sie verspotten oder verspotten möchten injizieren.
Führen Sie anschließend den Injector-Dienst mit dem Satz MockInjector::inject($this)
aus. Diese Ausführung kann in jedem Test oder in setUp
deklariert werden.
Nach der Ausführung des Injektors ist der mit #InjectMocks annotierte service
eine reale Instanz, die im Umfang der Testklasse verfügbar ist, und jede mit #Mock annotierte Abhängigkeit ist eine Instanz von MockObject, die über den Konstruktor in das Testsubjekt injiziert wird auch im Rahmen der Testklasse verfügbar sein.
MockInjectException
Ausnahme.#InjectMocks und #Mock funktionieren unabhängig und einzeln oder zusammen. Details zu jedem einzelnen:
Über den Konstruktor wird eine reale Instanz erstellt. Wenn der Konstruktor Parameter enthält, wird in jedem Parameter der folgende Wert in dieser Reihenfolge verwendet:
mock
der aus dem Attribut #[Mock] erstellt wurde, falls vorhanden;default
, wenn es sich um einen optionalen Parameter handelt;null
, wenn es als null
eingegeben wird;mock
, wenn es sich nicht um einen primitiven Typ handelt. In diesem Fall wird dieser mock
nicht in den TestCase-Bereich eingefügt;MockInjectException
ausgelöst.Hinweis: Sie können das Attribut #Mock für alle, einige oder keine Abhängigkeiten des Testobjekts verwenden.
Erstellt einen mock
, der in den TestCase-Bereich eingefügt wird, ohne den Konstruktor zu verwenden. Dieses Erstellungsverhalten ist identisch mit TestCase::createMock()
.