繁体   English   中英

使用注释在 Symfony 4.4 中测试控制器

[英]Testing Controllers in Symfony 4.4 while using annotations

我在使用 FOSRestBundle 和 JMSSserializer 测试 Symfony 4.4 中的控制器时遇到了问题。 我的控制器非常简单,通常只包含对其他服务的调用,但我使用的是 ParamConverter、Serializer、Deserializer 等。我永远不确定返回的字段是否是我期望的字段。

我想测试序列化/反序列化如何处理我的实体。 每当我在实体中添加字段或更改字段组时,测试都应该失败。

理想情况下,我会模拟我的服务并直接调用 Action,但我找不到任何地方,如何调用所有注释触发的 Action 方法。

除了对整个请求进行功能测试之外,还有其他测试方法吗?

Controller 动作我要测试:

    /**
     * @Rest\Post("/entity")
     * @Rest\Put("/entity/{entityId<\d+>?}")
     * @ParamConverter(name="entity", converter="app.request_body",options={
     *         "deserializationContext"={"groups"={
     *             "DetailsGroup",
     *             "nested"={"IdGroup"},
     *             "owner"={"IdGroup"}
     *         }}
     *     }
     * )
     * @Rest\View(serializerGroups={"IdGroup"}, statusCode=Response::HTTP_CREATED)
     * @param int|null $entityId
     * @param Entity $entity
     * @param ConstraintViolationListInterface $validationErrors
     * @return Entity
     * @throws InvalidArgumentException
     * @throws Exception
     */
    public function setEntityAction(?int $entityId, Entity $entity, ConstraintViolationListInterface $validationErrors): Entity
    {
        if ($validationErrors->count() > 0) {
            throw new InvalidArgumentException('...');
        }

        return $this->entityService->setEntity($entity, $this->getUser());
    }

当您要考虑要覆盖的注释时,测试 controller 通常需要大量设置。 通过单元测试进行设置,您只需实例化 controller 并模拟被调用的服务是不够的。

您可以做的是使用 Symfony 的 WebTestCase 运行功能测试,该测试通过启动的应用程序 kernel。这几乎可以在与在您的应用程序中实际调用它时发生的情况非常相似的设置中测试您的 controller。 这样做的缺点是,它还将运行所有服务。

您仍然可以尝试一些解决方法。 您可以直接在正在使用的服务容器中替换 controller 中调用的服务。 通过更改测试中的容器或通过提供自定义config/services_test.yaml将服务替换为“NullService”:

# config/services_test.yaml
services:
    App\Service\MyEntityService: # This is the original class name
        class: App\Service\NullService # This is the class name of the "null" service

这样,每当您注入MyEntityService时,您都会得到NullService 这将要求您扩展原始服务或拥有一个它们都可以实现的接口。 如果您有接口,您可能希望将其用作服务 ID 而不是原始的 class 名称。

这种方法的缺点是,您必须手动连接每个服务,并且必须为其创建一个虚拟替代品。 好处是,您可以很容易地返回您想要的数据,因为您可以控制实现。

另一种方法是更改测试本身的容器:

protected function testMyController(): void
{
    $kernel = self::bootKernel();

    $mock = $this->createMock(MyEntityService::class);

    $kernel->getContainer()->set(MyEntityService::class, $mock);
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM