Symfony 4.1: Как использовать внедрение зависимостей в UnitTest (Swift_Mailer)

В моем проекте Symfony4.1 я пытаюсь протестировать метод, который должен отправлять письма с использованием SwiftMailer с помощью модульного теста.

Мой тестовый класс выглядит так

namespace App\Tests;

use App\Controller\UserImageValidationController;
use Symfony\Bundle\FrameworkBundle\Tests\TestCase;

class UserImageValidationControllerTest extends TestCase
{

    private $mailer = null;
    public function __construct(\Swift_Mailer $testmySwiftMailer)
    {
        $this->mailer = $testmySwiftMailer;
    }

    public function testMail()
    {
        $controller = new UserImageValidationController();

        $controller->notifyOfMissingImage(
            'a',
            'b',
            'c',
            'd',
            $this->mailer
        );
    }
}

Проблема в том, что когда я запускаю ./bin/phpunit, я получаю исключение, говорящее

Uncaught ArgumentCountError: Too few arguments to function App\Tests\UserImageValidationControllerTest::__construct(), 0 [...] and exactly 1 expected [...]

Похоже, что в тестовой среде DI не работает.

Итак, я добавил

bind:
    $testmySwiftMailer: '@swiftmailer.mailer.default'

На мой config / services_test.yaml, но я все еще получаю ту же ошибку. Я также добавил в этот файл autowiring: true (просто чтобы попробовать), и он тоже не работает. Кроме того, я попытался использовать псевдоним службы, как указано в комментариях к файлу: все еще безуспешно.

Как мне внедрить swiftmailer в конструктор моего тестового примера?

В документации довольно ясно, что в базовом тестовом примере ничего не известно о контейнере Symfony. И, конечно же, оператор php new игнорирует контейнер. Что еще более важно, спросите себя, почему вы чувствуете необходимость тестировать класс Swift_Mailer? Для этого уже есть несколько тестов. Вы можете посмеяться над этим.

Cerad 14.06.2018 15:39

@Cerad Я не хочу тестировать Swift_Mailer, но я действительно хочу отправлять почту во время теста с помощью Swift_Mailer.

user6629162 14.06.2018 16:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
4 457
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Тесты не являются частью контейнера и не действуют как службы, поэтому ваше решение недействительно. Расширьте Symfony\Bundle\FrameworkBundle\Test\KernelTestCase и сделайте это вместо этого (сначала убедитесь, что ваша служба общедоступна):

protected function setUp()
{
    static::bootKernel();

    $this->mailer = static::$kernel->getContainer()->get('mailer');
}

protected function tearDown()
{
    $this->mailer = null
}

В этом случае вы должны определить службу или ее псевдоним как общедоступную.

olek07 31.01.2019 16:53

Нет в Symfony 4

Jorge 01.02.2019 17:02

Почему нет? Это не работает в Symfony 4.2 без определения псевдонима

olek07 01.02.2019 17:08

Очень хорошо объяснено здесь symfony.com/blog/new-in-symfony-4-1-simpler-service-testing

Jorge 02.02.2019 18:08

Мокинг службы не работает без определения службы или ее псевдонима как общедоступной.

olek07 02.02.2019 21:06

Принятый ответ не будет работать для служб, которые не определены как общедоступные. Однако после Symfony 4.1, чтобы иметь доступ к частным сервисам во время тестирования, вам необходимо получить сервис из специального контейнера для тестирования.

Из документации Symfony:

tests based on WebTestCase and KernelTestCase now access to a special container via the static::$container property that allows fetching non-removed private services

пример:

namespace App\Tests;

use App\Controller\UserImageValidationController;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;

class UserImageValidationControllerTest extends WebTestCase
{
    private $mailer = null;

    protected function setUp()
    {
        self::bootKernel();

        // gets the special container that allows fetching private services
        $container = self::$container;

        $this->mailer = $container->get('mailer');
    }

    public function testMail()
    {
        $controller = new UserImageValidationController();

        $controller->notifyOfMissingImage(
            'a',
            'b',
            'c',
            'd',
            $this->mailer
        );
    }
}

Другие вопросы по теме