gpt4 book ai didi

带有模拟服务的 Symfony 2 功能测试

转载 作者:行者123 更新时间:2023-12-03 11:56:29 27 4
gpt4 key购买 nike

我有一个 Controller ,我想为其创建功能测试。该 Controller 通过 MyApiClient 向外部 API 发出 HTTP 请求。类(class)。我需要模拟这个 MyApiClient类,所以我可以测试我的 Controller 如何响应给定的响应(例如,如果 MyApiClient 类返回 500 响应,它将做什么)。

创建 MyApiClient 的模拟版本没有问题通过标准的 PHPUnit mockbuilder 类:我遇到的问题是让我的 Controller 将此对象用于多个请求。

我目前在测试中执行以下操作:

class ApplicationControllerTest extends WebTestCase
{

public function testSomething()
{
$client = static::createClient();

$apiClient = $this->getMockMyApiClient();

$client->getContainer()->set('myapiclient', $apiClient);

$client->request('GET', '/my/url/here');

// Some assertions: Mocked API client returns 500 as expected.

$client->request('GET', '/my/url/here');

// Some assertions: Mocked API client is not used: Actual MyApiClient instance is being used instead.
}

protected function getMockMyApiClient()
{
$client = $this->getMockBuilder('Namespace\Of\MyApiClient')
->setMethods(array('doSomething'))
->getMock();

$client->expects($this->any())
->method('doSomething')
->will($this->returnValue(500));

return $apiClient;
}
}

似乎在发出第二个请求时正在重建容器,导致 MyApiClient再次实例化。 MyApiClient类通过注解(使用 JMS DI Extra Bundle)配置为服务,并通过注解注入(inject)到 Controller 的属性中。

如果可以的话,我会将每个请求拆分为自己的测试以解决此问题,但不幸的是我做不到:我需要通过 GET 操作向 Controller 发出请求,然后发布它返回的表单。我想这样做有两个原因:

1)表单使用CSRF保护,所以如果我直接POST到表单而不使用爬虫提交,表单没有通过CSRF检查。

2) 测试表单在提交时生成正确的 POST 请求是一种奖励。

有人对如何做到这一点有任何建议吗?

编辑:

这可以在以下不依赖于我的任何代码的单元测试中表示,因此可能更清楚:
public function testAMockServiceCanBeAccessedByMultipleRequests()
{
$client = static::createClient();

// Set the container to contain an instance of stdClass at key 'testing123'.
$keyName = 'testing123';
$client->getContainer()->set($keyName, new \stdClass());

// Check our object is still set on the container.
$this->assertEquals('stdClass', get_class($client->getContainer()->get($keyName))); // Passes.

$client->request('GET', '/any/url/');

$this->assertEquals('stdClass', get_class($client->getContainer()->get($keyName))); // Passes.

$client->request('GET', '/any/url/');

$this->assertEquals('stdClass', get_class($client->getContainer()->get($keyName))); // Fails.
}

这个测试失败了,即使我调用 $client->getContainer()->set($keyName, new \stdClass());在第二次调用 request() 之前

最佳答案

当您调用 self::createClient() ,你会得到一个 Symfony2 内核的启动实例。这意味着,所有配置都被解析和加载。现在发送请求时,您是第一次让系统完成它的工作,对吗?

在第一个请求之后,您可能想要检查发生了什么,因此,内核处于发送请求的状态,但它仍在运行。

如果您现在运行第二个请求,网络架构要求内核重新启动,因为它已经运行了一个请求。当您第二次执行请求时,将在您的代码中执行此重新启动。

如果您想在请求发送给它之前启动内核并对其进行修改(如您所愿),您必须关闭旧的内核实例并启动一个新的实例。

你可以通过重新运行 self::createClient() 来做到这一点。 .现在你必须再次应用你的模拟,就像你第一次做的那样。

这是您的第二个示例的修改代码:

public function testAMockServiceCanBeAccessedByMultipleRequests()
{
$keyName = 'testing123';

$client = static::createClient();
$client->getContainer()->set($keyName, new \stdClass());

// Check our object is still set on the container.
$this->assertEquals('stdClass', get_class($client->getContainer()->get($keyName)));

$client->request('GET', '/any/url/');

$this->assertEquals('stdClass', get_class($client->getContainer()->get($keyName)));

# addded these two lines here:
$client = static::createClient();
$client->getContainer()->set($keyName, new \stdClass());

$client->request('GET', '/any/url/');

$this->assertEquals('stdClass', get_class($client->getContainer()->get($keyName)));
}

现在您可能想要创建一个单独的方法,为您模拟新实例,因此您不必复制代码......

关于带有模拟服务的 Symfony 2 功能测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15341623/

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