【问题标题】:Accessing request container (event_dispatcher) within a test client在测试客户端中访问请求容器(event_dispatcher)
【发布时间】:2026-01-18 03:00:01
【问题描述】:

我在 Symfony 中创建了一个简单的测试用例。 因此,一个客户端应该侦听将在请求期间调度的事件。 但是什么都没有发生,因为请求有自己的范围,或者我不知道为什么我无法访问其中的调度程序。

$this->client = static::createClient();
self::$container = $this->client->getContainer();

$dispatcher = self::$container->get('event_dispatcher');

$dispatcher->addListener('example', function ($event) {
    // Never executed
});

$this->client->request('POST', $endpoint, $this->getNextRequestParameters($i), [$file], $this->requestHeaders);
$this->client->getResponse();

监听器永远不会被调用。 当我稍微调试一下时,我发现通过spl_object_hash($dispatcher) 的对象哈希在*别上与request 级别内的不同。 所以看来request有自己的世界,不理会外面的一切。

但问题是我如何才能让我的听众进入这个“世界”?

【问题讨论】:

    标签: unit-testing symfony phpunit symfony5 symfony-eventdispatcher


    【解决方案1】:

    我认为部分问题在于测试风格的混合。您有一个 WebTestCase 用于非常高水平的测试(请求和响应)。它不应该真正关心内部,即调用哪些服务或侦听器。它只关心给定输入 x(您的请求),您将获得输出 y(您的响应)。这可以确保始终满足用户感知的基本功能,而无需关心它是如何完成的。使这些测试非常灵活。

    通过查看容器和服务,您将进入较低级别的测试,即测试相互关联的服务。出于您已经发现的原因,这通常仅在同一过程中完成。更高级别的测试有 2 个独立的生命周期,一个用于测试本身,一个用于对应用程序的模拟 Web 请求,因此对象 ID 不同。

    解决方案是将某些东西发射到更高级别,例如通过设置标头或更改输出,您可以检查响应正文。您还可以写入一些日志文件并在请求该消息之前/之后检查日志。

    另一种选择是将整个测试移到不需要请求而仅使用服务的较低级别。为此,您可以使用KernelTestCase(而不是WebTestCase)而不是调用createClient(),而是调用bootKernel。这将使您可以访问您的容器,您可以在其中修改 EventDispatcher。您可以直接调用代码,而不是发送请求,例如如果您只想测试侦听器,则分派一个事件,或者您可以让您的控制器作为服务访问,然后手动创建一个请求,调用该操作,然后检查响应或您想要断言的任何其他内容。这大概如下所示:

    public function testActionFiresEvent()
    {
        $kernel = static::bootKernel();
    
        $eventDispatcher = $kernel->getContainer()->get('event_dispatcher');
    
        // ...
    
        $request = Request::create();
    
        // This might not work when the controller
        // You can create a service configuration only used by tests,
        // e.g. "config/services_test.yaml" and provide the controller service there
        $controller = $kernel->getContainer()->get(MyController::class);
    
        $response = $controller->endpointAction($request);
    
        // ...Do assertions...
    }
    

    【讨论】:

    • 非常感谢,但这很有趣,因为在 Symfony 4 中同样的测试用例可以完美运行。现在在 Symfony 5 中它坏了。但我会继续你的 KernelTest,然后它应该会更好:-) 谢谢
    最近更新 更多