模拟调用外部API

时间:2017-06-16 12:23:06

标签: symfony mocking phpunit deprecated symfony-3.3

今天,我尝试将我的项目升级到新版本的Symfony(3.3),我遇到了我的模拟问题。

直到今天,我正在做这样的嘲笑:

$client     = $this->makeClient();
$mockObject = new \stdClass();

$mock = $this->getMockBuilder('SomeClass')
            ->disableOriginalConstructor()
            ->setMethods(['method1', 'method2'])
            ->getMock();

$mock->expects($this->once())
    ->method('method1')
    ->will($this->returnValue($mockObject));

$client->getContainer()->set('my_service', $mock);

在这里,method1只是一个Guzzle帖子,没有别的。

现在,我收到以下错误:

  

设置" my_service"自Symfony 3.3以来不再支持预定义服务,并且在Symfony 4.0中不再支持预先定义的服务:1x

经过一些研究,似乎我无法使用我的代码的最后一行。 问题是,我无法找到或找到任何解决方案来解决此弃用问题。

2 个答案:

答案 0 :(得分:2)

解决问题的方法很少。

<强> TestDoubleBundle

TestDoubleBundle可以更轻松地创建测试双打。您可以使用依赖注入标记来自动使用存根或伪造替换服务。

覆盖容器

另一种方法是在测试环境中扩展容器,因此它允许存根。这是一个想法的草稿:

<?php

namespace Zalas\Test\DependencyInjection;

use Symfony\Component\DependencyInjection\Container;

class MockerContainer extends Container
{
    /**
     * @var object[] $stubs
     */
    private $stubs = array();

    public function stub($serviceId, $stub)
    {
        if (!$this->has($serviceId)) {
            throw new \InvalidArgumentException(sprintf('Cannot stub a non-existent service: "%s"', $serviceId));
        }

        $this->stubs[$serviceId] = $stub;
    }

    /**
     * @param string  $id
     * @param integer $invalidBehavior
     *
     * @return object
     */
    public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE)
    {
        if (array_key_exists($id, $this->stubs)) {
            return $this->stubs[$id];
        }

        return parent::get($id, $invalidBehavior);
    }

    /**
     * @param string $id
     *
     * @return boolean
     */
    public function has($id)
    {
        if (array_key_exists($id, $this->stubs)) {
            return true;
        }

        return parent::has($id);
    }
}

要启用此容器,您需要覆盖getContainerBaseClass中的AppKernel方法:

/**
 * @return string
 */
protected function getContainerBaseClass()
{
    if ('test' == $this->environment) {
        return '\Zalas\Test\DependencyInjection\MockerContainer';
    }

    return parent::getContainerBaseClass();
}

您可能需要稍微调整一下代码,或者将MockerContainer::$stubs声明为静态(尽管如果您之前的方法有效,则不需要它 - 如果您需要存根多个请求,则可能需要它)。

现在你应该能够使用容器来存储这样的服务:

$client->getContainer()->stub('my_service', $myServiceStub);

使用合成服务

解决您的问题的另一种方法是将您的服务定义为synthetic。您可以编写一个编译器传递,它只会在测试环境中将服务标记为合成。

答案 1 :(得分:1)

您的问题也在讨论here

您可以查看this osservation

  

请注意,在转移到3.3时,您不需要修复弃用。   但是当你搬到4.0时你会的。

this workaround

  

好吧,您可以将这些测试标记为@legacy,以避免失败   暂时,给你时间迁移测试,如果需要的话   时间。这是弃用的全部内容:您可以迁移   逐步(我也喜欢尽快删除折旧   可能,但对于其中一些,可能需要更多时间)