gpt4 book ai didi

symfony - 如何在 phpunit 功能测试中模拟 symfony Controller 的自动连接服务?

转载 作者:行者123 更新时间:2023-12-03 23:16:05 27 4
gpt4 key购买 nike

非问题上下文

假设在 Symfony 3.3 中,我们有一个默认的 Controller 来绘制“Hello, world!”:

class DefaultController extends Controller
{
public function indexAction() : Response
{
return new Response( 'Hello, world!' );
}
}

如果我想测试它,我只需创建一个 WebTestCase 并在客户端或爬虫上做一些断言,例如
class DefaultControllerTest extends WebTestCase
{
public function testIndex()
{
$client = static::createClient();

$crawler = $client->request( 'GET', '/route/to/hello-world/' );

$this->assertEquals( 200, $client->getResponse()->getStatusCode() );
$this->assertContains( 'Hello', $crawler->filter( 'body' )->text() );
}
}

这很好用。

有问题的上下文

假设我们有一些经过单元测试的服务。例如 IdGenerator当我们需要时基于某种算法创建新 ID 的服务,它们只是纯文本:
class IdGenerator
{
public function generateNewId() : string;
}

假设我们通过 注入(inject)它 Autowiring 进入 Controller 。我们预计 Controller 会说 Hello, world, on request 8bfcedbe1bf3aa44e0545375f0e52f6b969c50fb!这一堆字符来自IdGenerator。
class DefaultController extends Controller
{
public function indexAction( IdGenerator $idGenerator ) : Response
{
$id = $idGenerator->generateNewId();
$message = sprintf( 'Hello, world, on request %s!', $id );
return new Response( $message );
}
}

当然,我可以在浏览器中多次重新加载页面,并且每次都会看到文本随着时间的推移使用新的 ID 发生变化。

但这不是自动化测试应该采用的方式。我们应该模拟 IdGenerator,所以它返回一个特定的 id断言:
class DefaultControllerTest extends WebTestCase
{
public function testIndex()
{
$id = 'test-id-test-id-test-id';
$idGenerator = $this->createMock( IdGenerator::class );
$idGenerator->method( 'generateNewId' )->willReturn( $id );

// What do I have to do with $idGenerator now here????

$client = static::createClient();

// Do something else here?

$crawler = $client->request( 'GET', '/admin/flights/search/' );

$this->assertEquals( 200, $client->getResponse()->getStatusCode() );
$this->assertContains( $id, $crawler->filter( 'body' )->text() );
}
}

我已经测试过从内核、客户端获取容器,并在那里设置服务,它确实 不是 工作:
    $id = 'test-id-test-id-test-id';
$idGenerator = $this->createMock( IdGenerator::class );
$idGenerator->method( 'generateNewId' )->willReturn( $id );

$client = static::createClient();
$kernel = $client->getKernel();
$container = $kernel->getContainer();
$container->set( 'My\Nice\Project\Namespace\IdGenerator', $idGenerator );

它仍然得到自动接线的,而不是我想要的(模拟)。

问题

如何设置 WebTestCase 以便 Autowiring 连接我的模拟服务?

最佳答案

简短的回答是你没有。

WebTestCase 用于更高级别的测试,有时称为功能或集成测试。它们旨在使用实际服务或适当的测试替代方案,例如用于测试的 SQLite 数据库而不是 MySQL 或 Paypal 沙盒而不是生产服务。如果您想测试服务并用模拟或 stub 替换其依赖项,则应改为编写单元测试。

如果您想用虚拟实现替换您的服务,例如总是根据输入返回相同的 id 或散列,您可以替换 config/services_test.yaml 中容器配置中的别名只要您的应用程序使用测试应用程序环境(默认情况下 WebTestCase 会这样做),就会使用它。您也可以尝试在运行时更改容器,但是因为 Symfony 编译容器然后卡住它,即不允许对容器进行任何更改,这可能会很棘手并且不推荐。

作为进一步的引用,Symfony 4.1 提供了一个包含所有服务的容器,包括私有(private)服务,暴露:https://symfony.com/blog/new-in-symfony-4-1-simpler-service-testing
这可能对您的情况没有帮助,但它显示了您如何与 WebTestCase-tests 中的服务容器交互。

关于symfony - 如何在 phpunit 功能测试中模拟 symfony Controller 的自动连接服务?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50667378/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com