Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як впровадження залежностей робить код тестованим і що таке тестові дублери?

Проблема: клас сам створює свої залежності - і в тесті їх неможливо замінити.

class OrderService
{
    public function place(Order $order): void
    {
        $gateway = new StripeGateway(config('services.stripe.key'));   // справжній платіж у тесті?
        $gateway->charge($order->total);
    }
}

Впровадження залежностей - клас отримує залежності ззовні (зазвичай через конструктор):

class OrderService
{
    public function __construct(private PaymentGateway $gateway) {}

    public function place(Order $order): void
    {
        $this->gateway->charge($order->total);
    }
}

Сервіс-контейнер Laravel створить OrderService і підставить реалізацію PaymentGateway, зареєстровану в провайдері. А в тесті можна підставити тестовий дублер.

Види тестових дублерів (за Джерардом Месарошем):

  • dummy - об'єкт-заглушка, що лише заповнює параметр і не використовується;
  • stub - повертає заздалегідь задані відповіді («платіж завжди успішний»);
  • spy - запам'ятовує виклики, щоб потім перевірити, як його використовували;
  • mock - заздалегідь налаштовані очікування викликів, що перевіряються автоматично;
  • fake - робоча спрощена реалізація (база в пам'яті, платіжний шлюз, що зберігає транзакції в масиві).

У Laravel багато фейків уже готові:

Mail::fake();
Queue::fake();
Http::fake(['api.stripe.com/*' => Http::response(['status' => 'succeeded'])]);
Storage::fake('s3');

$this->app->instance(PaymentGateway::class, new FakePaymentGateway());

Чому fake часто кращі за mock: mock перевіряє, як код викликає залежність (порядок, аргументи), і ламається при будь-якому рефакторингу. Fake перевіряє результат («після оформлення в шлюзі є одна транзакція на 500 грн») - тести стійкіші.

Пастка надмірних моків: тест, де все замокано, перевіряє лише те, що код викликає моки так, як ви їх налаштували. Моки - для меж системи (сторонні API, пошта, час, випадковість), а не для кожного внутрішнього класу.

Докладніше в документації: Martin Fowler: Test Double

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

Схожі питання