Автоматическое внедрение макетов в испытуемых с помощью аннотаций #InjectMocks и #Mock для ускорения модульного тестирования с помощью PHPUnit.
Лея — это португальская версия.
Для установки в среду разработки:
composer require --dev silasyudi/inject-mocks
Используя аннотации #InjectMocks и #Mock в тестовых классах, вы можете автоматически внедрять макеты в объекты тестирования.
В типичном сценарии мы бы сделали это так:
class SomeTest extends PHPUnit Framework TestCase
{
public void testSomething()
{
$ someDependency = $ this -> createMock (Dependency::class);
$ anotherDependency = $ this -> createMock (AnotherDependency::class);
. . .
$ subject = new Service ( $ someDependency , $ anotherDependency , ...);
. . .
}
...
Такой подход усложняет сопровождение, поскольку если объект тестирования будет изменен путем добавления, уменьшения или замены зависимостей, вам придется менять его в каждом тесте.
С помощью аннотаций #InjectMocks/#Mock мы абстрагируем эти изменения объекта тестирования. Пример:
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.
}
...
Как и в примере из предыдущего раздела, атрибут #InjectMocks необходимо поместить в свойство субъекта тестирования, которое вы хотите протестировать, а атрибут #Mock должен быть помещен в свойства, соответствующие зависимостям, которые вы хотите имитировать или вводить.
После этого запустите службу инжектора с предложением MockInjector::inject($this)
. Это выполнение может быть объявлено в каждом тесте или в setUp
.
После выполнения инжектора service
, помеченная #InjectMocks, станет реальным экземпляром, доступным в области тестового класса, а каждая зависимость, помеченная #Mock, будет экземпляром MockObject, внедренным в объект тестирования через конструктор, и будет также быть доступным в рамках тестового класса.
MockInjectException
.#InjectMocks и #Mock работают независимо и по отдельности или вместе. Подробности о каждом:
Он создаст реальный экземпляр через конструктор, и если в конструкторе есть параметры, в каждом параметре будет использоваться следующее значение в следующем порядке:
mock
созданный на основе атрибута #[Mock], если он существует;default
, если это необязательный параметр;null
если он введен как null
;mock
если он не является примитивным типом. В этом случае этот mock
не будет внедрен в область действия TestCase;MockInjectException
.Наблюдение: вы можете использовать атрибут #Mock для всех, некоторых или ни одной из зависимостей испытуемого.
Создаст mock
, внедренный в область действия TestCase, без использования конструктора. Это поведение создания идентично TestCase::createMock()
.