Symfony 4.1:如何在单元测试中使用依赖注入(Swift_Mailer)

5
在我的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注入到我的测试用例构造函数中?


1
文档非常明确,基本测试用例不知道 Symfony 容器。而且,php 的 new 运算符也不了解容器。更重要的是,请问自己为什么要测试 Swift_Mailer 类?它已经有了一堆测试。你可以考虑使用模拟来测试。 - Cerad
@Cerad 我不想测试Swift_Mailer,但我真的想在我的测试中使用Swift_Mailer发送邮件。 - user6629162
2个回答

3

测试不是容器的一部分,也不作为服务,所以您的解决方案无效。相反,请扩展Symfony\Bundle\FrameworkBundle\Test\KernelTestCase并进行修改(首先确保您的服务是公共的):

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

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

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

1
在这种情况下,您应该将服务或其别名定义为公共的。 - olek07
1
不是在Symfony 4中 - Jorge
为什么不呢?在Symfony 4.2中没有定义别名无法工作。 - olek07
2
非常好的解释在这里 https://symfony.com/blog/new-in-symfony-4-1-simpler-service-testing - Jorge
1
在没有将服务或其别名定义为公共的情况下,模拟服务是无法正常工作的。 - olek07

2
被接受的答案对于未定义为公共服务的服务将无法使用。但是,在Symfony 4.1之后,为了能够在测试过程中访问私有服务,您需要从特殊的测试容器中获取服务。
根据Symfony文档:
基于WebTestCase和KernelTestCase的测试现在可以通过static::$container属性访问一个特殊的容器,该容器允许获取未删除的私有服务。
示例:
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
        );
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接