Php Symfony功能测试-如何使用请求模拟控制器注入服务(提交)
我如何在功能测试用例中模拟一个正在进行“请求”(表单/提交)的服务。在我发出请求之后,我对容器所做的所有更改和模拟都将丢失 我正在使用Symfony 4或5。此处发布的代码也可以在此处找到: 我有以下情况:Php Symfony功能测试-如何使用请求模拟控制器注入服务(提交),php,unit-testing,symfony,Php,Unit Testing,Symfony,我如何在功能测试用例中模拟一个正在进行“请求”(表单/提交)的服务。在我发出请求之后,我对容器所做的所有更改和模拟都将丢失 我正在使用Symfony 4或5。此处发布的代码也可以在此处找到: 我有以下情况: SomeActions服务被注入控制器构造函数 在功能单元测试中,我尝试模拟SomeActions函数,以检查它们是否执行(它发送电子邮件或类似的东西) 我模拟服务并在单元测试中覆盖它: $container->set('App\Model\SomeActions', $someA
- SomeActions服务被注入控制器构造函数
- 在功能单元测试中,我尝试模拟SomeActions函数,以检查它们是否执行(它发送电子邮件或类似的东西)
$container->set('App\Model\SomeActions', $someActions);
现在在测试中,我做了一个$client->submit($form)我知道它会终止内核
我的问题是:如何在$client->submit($form)之后将模拟的$someActions注入容器中代码>
下面是我添加到symfony演示应用程序的示例代码
服务业。yaml
App\Model\SomeActions:
public: true
SomeController.php
<?php
namespace App\Controller;
use App\Model\SomeActions;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
/**
* Controller used to send some emails
*
* @Route("/some")
*/
class SomeController extends AbstractController
{
private $someActions;
public function __construct(SomeActions $someActions)
{
//just dump the injected class name
var_dump(get_class($someActions));
$this->someActions = $someActions;
}
/**
* @Route("/action", methods="GET|POST", name="some_action")
* @param Request $request
* @return Response
*/
public function someAction(Request $request): Response
{
$this->someActions->doSomething();
if ($request->get('send')) {
$this->someActions->sendEmail();
}
return $this->render('default/someAction.html.twig', [
]);
}
}
<?php
namespace App\Tests\Controller;
use App\Model\SomeActions;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class SomeControllerTest extends WebTestCase
{
public function testSomeAction()
{
$client = static::createClient();
// gets the special container that allows fetching private services
$container = self::$container;
$someActions = $this->getMockBuilder(SomeActions::class)
->disableOriginalConstructor()
->getMock();
//expect that sendEmail will be called
$someActions->expects($this->once())
->method('sendEmail');
//overwrite the default service: class: Mock_SomeActions_e68f817a
$container->set('App\Model\SomeActions', $someActions);
$crawler = $client->request('GET', '/en/some/action');
//submit the form
$form = $crawler->selectButton('submit')->form();
$client->submit($form);
//after submit the default class injected in the controller is "App\Model\SomeActions" and not the mocked service
$response = $client->getResponse();
$this->assertResponseIsSuccessful($response);
}
}
解决方案是禁用内核重新启动:
$client->disableReboot();
如果一个人挖掘得足够深,能够理解引擎盖下发生的事情,这是有意义的;
我仍然不确定是否还有更直接的答案
public function testSomeAction()
{
$client = static::createClient();
$client->disableReboot();
...
这个答案对你有帮助吗?(注意最后一句话)不是真的,它的解决方案是什么?这只是我的猜测-但您可能需要注入模拟服务两次(在获取页面之前和提交表单之前)。$client->disableReboot()$客户->提交($form)代码>如果我这样做,那么我就实现了我想要的。不确定这是否是最好的方法。此外,在static::createClient()
之前对容器所做的更改似乎丢失了,因此模拟必须在客户端创建之后进行。
public function testSomeAction()
{
$client = static::createClient();
$client->disableReboot();
...