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

问题描述 投票:1回答:1

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

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

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

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

我要测试的控制器动作:

    /**
     * @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());
    }

php unit-testing symfony functional-testing fosrestbundle
1个回答
0
投票

测试控制器通常需要进行大量设置,以便说明要覆盖的注释。仅通过实例化控制器并模拟调用的服务的单元测试来进行设置是不够的。

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

您仍然可以尝试一些解决方法。您可以直接在正在使用的服务容器中替换控制器中调用的服务。通过更改测试中的容器或提供自定义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,而不是原始的类名。

此方法的缺点是,您必须手动连接每个服务并必须为其创建虚拟替换。好处是,您可以在控制实现的同时轻松返回所需的数据。

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

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

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

    $kernel->getContainer()->set(MyEntityService::class, $mock);
}
© www.soinside.com 2019 - 2024. All rights reserved.