Symfony 4功能测试中的模拟服务



我正在测试一个服务,该服务主要是序列化对象并通过服务将其发送到外部系统。

如果我创建典型的单元测试,我会模拟序列化程序和服务的响应,后者会联系外部系统。事实上,除了在我的对象中调用一堆setter方法之外,剩下的测试就不多了。

另一种选择是使用KernelTestCase并创建一个功能测试,这很好,只是我不想联系外部系统,而是只对这个"外部"服务使用mock。

有没有可能在Symfony 4中实现这一点?或者有其他方法可以解决这个问题吗?

我现在正在做的是:

<?php
namespace AppTestsService;
use AppServiceMyClassService;
use AppServiceExternalClientExternalClient;
use JMSSerializerSerializer;
use JMSSerializerSerializerInterface;
use PsrHttpMessageRequestInterface;
use PsrLogLoggerInterface;
use SymfonyBundleFrameworkBundleTestKernelTestCase;
use SymfonyComponentHttpFoundationRequest;
class MyClassServiceTest extends KernelTestCase
{
/** @var LoggerInterface */
private $logger;
/** @var Serializer */
private $serializer;
/** @var ExternalClient */
private $externalClient;
/** @var RequestInterface */
private $request;
/** @var MyClassService */
private $myClassService;
public function setUp()
{
$kernel = self::bootKernel();
$this->logger = $kernel->getContainer()->get(LoggerInterface::class);
$this->serializer = $kernel->getContainer()->get(SerializerInterface::class);
$this->externalClient = $this->createMock(ExternalClient::class);
}
public function testPassRegistrationData()
{
$getParams = [
'amount'          => '21.56',
'product_id'      => 867,
'order_id'        => '47t34g',
'order_item_id'   => 2,
'email'           => 'kiki%40bubu.com',
];
$this->generateMyClassService($getParams);
$userInformation = $this->myClassService->passRegistrationData();
var_dump($userInformation);
}
/**
* generateMyClassService
*
* @param $getParams
*
* @return MyClass
*/
private function generateMyClassService($getParams)
{
$this->request = new Request($getParams, [],  [], [], [], [], null);
$this->myClassService = new MyClassService(
$this->logger,
$this->serializer,
$this->externalClient,
$this->request
);
}
}

返回此错误:

SymfonyComponentDependencyInjectionExceptionRuntimeException: Cannot autowire service "AppServiceMyClassConfirmationService": argument "$request" of method "__construct()" references class "SymfonyComponentHttpFoundationRequest" but no such service exists.

您不应该将Request注入到您的服务中。您应该使用SymfonyComponentHttpFoundationRequestStack而不是Request。此外,您应该检查$requestStack->getCurrentRequest()是否未返回null。我想您在初始化容器的过程中会遇到这样的错误,但您只执行了一个脚本(测试(,当然,上面没有Request

由于整个事情需要更多的调整,我发布了我的解决方案,Nikita的回答引导我:

正如他所建议的,我用RequestStack代替了"我服务中的请求",结果很好:

/**
* @param LoggerInterface     $logger
* @param SerializerInterface $serializer
* @param ExternalClient      $externalClient
* @param RequestStack        $requestStack
*/
public function __construct(
LoggerInterface $logger,
SerializerInterface $serializer,
ExternalClient $externalClient,
RequestStack $requestStack
) {
$this->logger = $logger;
$this->serializer = $serializer;
$this->externalClient = $externalClient;
$this->request = $requestStack->getCurrentRequest();
$this->params = $this->request->query;
}

在我的测试中,我伪造了这样的请求:

$this->request = new Request($getParams, [], [], [], [], [], null);
$this->requestStack = new RequestStack();
$this->requestStack->push($this->request);

然而,由于我的类还要求记录器和序列化程序,因此修复了出现的下一个问题。对于Logger,我使用了一个我专门为这种测试情况创建的通用Loggerclass。但这让我只能得到串行器,我想要真正的串行器,否则我可能会坚持使用一个几乎无用的UnitTest。

我就是这么做的:

public function setUp()
{
$kernel = self::bootKernel(); 
$container = self::$container;
$this->serializer = $container->get('jms_serializer.serializer');
}

这给了我容器中真正的序列化程序。现在,我可以让我的模拟外部客户给我模拟的答案,我可以在不打扰外部服务的情况下测试我的服务的反应。

最新更新