Верх страницы
Обложка к записи Как тестировать Hard Dependencies в PHPUnit с помощью Mockery
Время для прочтения: 1 мин. 3 сек.

Как тестировать Hard Dependencies в PHPUnit с помощью Mockery

Если у вас возникают вопросы: Что такое Hard Dependencies и почему это плохо? Вы можете прочитать в статье «Dependency Injection the best design pattern«.

Внедрения зависимостей (Dependency Injection) один из основных принципов, которых нужно придерживаться для написание качественного кода.

Но иногда мы сталкиваемся с проблемами, когда избежать зависимостей невозможно или же это занимает слишком много времени.

Сложность заключается в том, что зависимости мы не должны тестировать, мы должны создать для них заглушки.

Установка Mockery

Нам понадобиться библиотеку Mockery:

composer require mockery/mockery --dev

Фикстуры для Mockery

Что такое фикстуры можно прочитать в статье «Модульное тестирование (Unit tests) с помощью PHPUnit«.

Для работы библиотеки Mockery нам нужно изменить фикстуры:

use PHPUnit\Framework\TestCase;

class Test_Bird extends TestCase {

	 /**
	 * Setup test
	 */
	public function setUp(): void {
		Mockery::resetContainer();
		parent::setUp();
	}

	/**
	 * End test
	 */
	public function tearDown(): void {
		Mockery::close();
		parent::tearDown();
	}

}

Первый тест Hard Dependency

Пример тестируемого класса:

function bird_say(): string {
   $duck = new \Bird\Duck();
   return $duck->say();
}

Создаем заглушку для класса \Bird\Duck:

$mock = Mockery::mock( 'Bird\Duck' );
$mock->shouldReceive('say')
    ->once()
    ->andReturn( 'krya' );

Заглушку мы не можем передать в тестируемую функцию исходя из задачи. Но мы можем ее переопределить с помощью overload в библиотеке Mockery:

public function test_bird_say() {
    $mock = Mockery::mock( 'overload:Bird\Duck' );
    $mock->shouldReceive('say')
        ->once()
        ->andReturn( 'krya' );

    $this->assertSame( 'krya', bird_say() );
}

Тест работает, но теперь все объекты Bird\Duck в тестовом классе, которые идут после тестового метода будут иметь такую же заглушку. Это очень плохо так как следующий пример вызывает ошибку из-за того, что Bird\Duck в тесте test_bird_say_2 уже объявлен. Этого быть не должно.

public function test_bird_say() {
    $mock = Mockery::mock( 'overload:Bird\Duck' );
    $mock->shouldReceive('say')
        ->once()
        ->andReturn( 'krya' );

    $this->assertSame( 'krya', bird_say() );
}

public function test_bird_say_2() {
    $mock = Mockery::mock( 'overload:Bird\Duck' );
    $mock->shouldReceive('say')
        ->once()
        ->andReturn( 'no-krya' );

    $this->assertSame( 'no-krya', bird_say() );
}

Первый хороший тест Hard Dependency

Для того, чтобы избежать зависимости между тестовыми методами, нужно добавить аннотации к каждому тестовому методу, который использует overload:

/**
 * @runInSeparateProcess
 * @preserveGlobalState disabled
 */
public function test_bird_say() {
    $mock = Mockery::mock( 'overload:Bird\Duck' );
    $mock->shouldReceive('say')
        ->once()
        ->andReturn( 'krya' );

    $this->assertSame( 'krya', bird_say() );
}

/**
 * @runInSeparateProcess
 * @preserveGlobalState disabled
 */
public function test_bird_say_2() {
    // ...
}
  • @runInSeparateProcess — Указывает, что тест должен выполняться в отдельном процессе PHP;
  • @preserveGlobalState disabled — нужно запретить сохранять глобальное состояние.

Теперь все работает как надо!

Краткий обзор

Для тестирования Hard Dependencies нам нужно сделать следующее:

  • Установить Mockery
  • Обновить фикстуры в тестовом классе
  • При создании заглушки добавить overload
  • Добавить аннотации к тестируемому методу

Источник: WP Punk.

Автор: Кобзарёв Михаил

Русский разработчик с 20-ти летним стажем. Работаю с PHP, ООП, JavaScript, Git, WordPress, Битрикс, Joomla, Drupal, OpenCart, DLE, Laravel, Moonshine, Symfony, SuiteCRM.

Оптимизирую сайты под Google Page Speed, настраиваю импорты для больших магазинов на WooCommerce + WP All Import. Пишу плагины на заказ. Все мои услуги.

Веду блог о разработке, дайджест в телеграмме и в ВК.

Вы всегда можете нанять меня.

Комментарии
Подписаться
Уведомить о
guest

0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии
Предыдущая запись
Следующая запись

Давайте дружить
в Telegram

Авторский блог вашего покорного слуги в Telegram про web, программирование, алгоритмы, инструменты разработчика, WordPress, Joomla, Opencart, Laravel, Moonshine, фильмы и сериалы