我试图在我的PHPUnit WebTestCase中测试需要会话的方法,但没有成功。
PHP 8.0,Symfony 5.4
下面是我的代码:
当用户登录时,我在会话中保存自定义信息:
public function methodCalledAfterLoginSuccess(int $id_internal_network, SessionInterface $session): Response
{
$session->set('current_internal_network',$id_internal_network);
return $this->redirectToRoute("dashboard");
}
在一些控制器中,我得到这样的值:
#[Route('/contract/list', name: 'list_contract')]
public function listContracts(Request $request, SessionInterface $session): Response
{
$currentInternalNetwork = $session->get('current_internal_network');
(...)
一切都很好。然后,我设置我的功能测试:
class SomeController extends WebTestCase
public function setUp(): void
{
$this->client = static::createClient([], ['HTTPS' => true]);
parent::setUp();
}
public function testShowContractSearchForm(): void
{
$session = new Session(new MockFileSessionStorage());
$session->start();
$this->login('admin');
dd($session->get('current_internal_network'));
$this->client->request('GET', '/contract/list');
self::assertResponseIsSuccessful();
}
但是$session->get('current_internal_network')
是空的
方法$this->login('admin');
将提交一个登录表单与正确的信息,所以我“登录”在我的测试,这部分是好的。
我的框架。yaml:
when@test:
framework:
test: true
session:
storage_factory_id: session.storage.factory.mock_file
在我的测试中,我不需要特别访问$session,但是方法listContracts()
需要有一个会话,其中填充了登录部分的正确信息。
我错过了什么?
2条答案
按热度按时间py49o6xq1#
我也遇到了同样的问题,最终实现了我自己的KernelBrowser::loginUser()替代方案。在我的例子中,我有一个多租户应用程序,我在用户会话中保留了活动租户的ID。
只是为了上下文,这里是我的用户案例:
我使用一些事件订阅者来验证(1)当前用户是否可以访问用户会话中的租户,以及(2)所有转换为Doctrine Entities的请求参数都属于当前活动的租户。
这是我的第一道防线,防止人们试图访问他们不应该访问的东西。
在我的功能测试中,我使用KernelBrowser来调用像
/task/1
这样的URL。一个“任务”属于一个单一的租户,需要一个经过身份验证的用户来访问它,所以测试用例必须与一个经过身份验证的用户一起工作,并与一个存储在会话中的租户一起工作。我不想介绍一种只用于测试的方式,如何以其他方式指定租户ID(例如/task/1?tenant=1)。我认为这样的事情是一场等待发生的安全灾难。
无论如何,这里是帮助器方法,它创建会话并向其添加一些参数,然后在客户端示例中设置正确的会话cookie。
它的工作原理就像一个魅力,我正在考虑提交一个PR,其中
KernelBrowser::loginUser()
将接受一个应该注入模拟会话的属性的键/值对数组。关键是在向其添加安全相关内容的同时设置会话ID。
我相信有一个正确的方法可以在以后访问客户端会话,从代码的任何地方,但我还没有找到它。
我希望能帮上忙。
bvk5enib2#
这应该可以做到这一点(作为一个例子,将一个区域设置保存到会话中):