Injection automatique de simulations dans les sujets de test via les annotations #InjectMocks et #Mock, pour accélérer les tests unitaires avec PHPUnit.
Leia a versão em português ici.
Pour installer dans l'environnement de développement :
composer require --dev silasyudi/inject-mocks
En utilisant les annotations #InjectMocks et #Mock dans les classes de test, vous pouvez automatiquement injecter des simulations dans les sujets de test.
Dans un scénario typique, nous procéderions comme ceci :
class SomeTest extends PHPUnit Framework TestCase
{
public void testSomething()
{
$ someDependency = $ this -> createMock (Dependency::class);
$ anotherDependency = $ this -> createMock (AnotherDependency::class);
. . .
$ subject = new Service ( $ someDependency , $ anotherDependency , ...);
. . .
}
...
Cette approche entraîne la difficulté de la maintenance, car si le sujet de test est modifié, soit en ajoutant, diminuant ou remplaçant des dépendances, vous devrez le changer à chaque test.
Avec les annotations #InjectMocks/#Mock, nous résumons ces changements de sujets de test. Exemple:
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.
}
...
Comme dans l'exemple de la rubrique précédente, l'attribut #InjectMocks doit être placé sur la propriété du sujet de test que vous souhaitez tester, et l'attribut #Mock doit être placé sur les propriétés correspondant aux dépendances que vous souhaitez simuler ou injecter.
Après cela, exécutez le service d'injection avec la phrase MockInjector::inject($this)
. Cette exécution peut être déclarée dans chaque test ou dans setUp
.
Après avoir exécuté l'injecteur, le service
annoté avec #InjectMocks sera une instance réelle disponible dans le périmètre de la classe de test, et chaque dépendance annotée avec #Mock sera une instance de MockObject, injectée dans le sujet de test via le constructeur, et être également disponible dans le cadre de la classe de test.
MockInjectException
.#InjectMocks et #Mock fonctionnent indépendamment et seuls, ou ensemble. Détails sur chacun :
Cela créera une instance réelle via le constructeur, et s'il y a des paramètres dans le constructeur, la valeur suivante sera utilisée dans chaque paramètre, dans cet ordre :
mock
créée à partir de l'attribut #[Mock], s'il en existe un ;default
s'il s'agit d'un paramètre facultatif ;null
s'il est tapé comme null
;mock
s'il ne s'agit pas d'un type primitif. Dans ce cas, ce mock
ne sera pas injecté dans le scope TestCase ;MockInjectException
sera levée.Obs. : Vous pouvez utiliser l'attribut #Mock sur toutes, certaines ou aucune des dépendances du sujet de test.
Créera une mock
injectée dans la portée TestCase, sans utiliser le constructeur. Ce comportement de création est identique à TestCase::createMock()
.