Symfony 3.4 功能测试
Symfony 3.4 Functional tests
我在使用 symfony 3.4 进行功能测试时遇到错误已经有一段时间了。
我的应用程序 运行 自定义 GuardAuthenticator,用于在 CAS 身份验证中对我的用户进行身份验证。这只是为了解释上下文。在我的测试中,我不想使用它,我想使用特定的身份验证系统。
我写了功能测试。我用以下内容开始我的测试环境:
# app/config/config_test.yml
imports:
- { resource: config_dev.yml }
framework:
test: ~
session:
storage_id: session.storage.mock_file
name: MOCKSESSION
profiler:
collect: false
根据官方 Symfony 文档,我扩展了 symfony WebTestCase 来为我的测试设置特定的身份验证令牌 How to Simulate HTTP Authentication in a Functional Test
namespace Test\AppBunble\WebTestCase;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as SfTestCase;
class WebTestCase extends SfTestCase
{
/**
*
* {@inheritDoc}
* @see \PHPUnit_Framework_TestCase::setUp()
*/
public function setUp()
{
$this->client = static::createClient();
$this->container = $this->client->getContainer();
$this->entityManager = $this->container->get('doctrine.orm.entity_manager');
parent::setUp();
}
public function logInAs($username)
{
$user = $this->entityManager->getRepository(User::class)->loadUserByUsername($username);
$session = $this->client->getContainer()->get('session');
$token = new PostAuthenticationGuardToken($user, 'main', $user->getRoles());
$session->set('_security_main', serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
}
最后,我写了我的(简单的)测试:
namespace Tests\AppBundle\Controller;
use Tests\AppBundle\WebTestCase;
class DefaultControllerTest extends WebTestCase
{
public function testIndex()
{
$this->logInAs('admin');
$crawler = $this->client->request('GET', '/');
$this->assertTrue($client->getResponse()->isSuccessful(), 'response status is 2xx');
}
}
我运行 phpunit :
$ ./vendor/bin/simple-phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
Testing app Test Suite
<br />
<b>Error</b>: <font color="FF0000"><b>Internal script failure</b><br />
为了调试,我修改了我的测试:
public function testIndex()
{
$this->logInAs('admin');
//$crawler = $this->client->request('GET', '/');
//$this->assertTrue($client->getResponse()->isSuccessful(), 'response status is 2xx');
}
我运行 phpunit :
./vendor/bin/simple-phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
Testing app Test Suite
. 1 / 1 (100%)
Time: 797 ms, Memory: 27.75MB
OK (1 test, 0 assertions)
经过大量测试后,我在调用测试时发现:
$this->client->request('GET', '/')
它崩溃了。
更新:另一个测试。
如果我 运行 这个 :
public function testIndex()
{
$this->logInAs('admin');
$token = $this->client->getContainer()->get('security.token_storage');
var_dump($token->getToken());
//$crawler = $this->client->request('GET', '/');
//$this->assertTrue($client->getResponse()->isSuccessful(), 'response status is 2xx');
}
它return我NULL
...没有令牌。
更新 2
我深入研究代码以返回到 symfony 停止的地方。在Symfony\Component\EventDispatcher\EventDispatcher
class.
的doDispatch
方法中
它触发 `kernel.event' 事件的侦听器。当它触发名为“Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener”的侦听器时=>“内部脚本失败”。
更新 3
如果我比较 dev.log(代表我在浏览器中 运行 应用程序时的日志),我在请求中有此日志:
[2020-10-23 13:55:56] request.INFO: Matched route "app_homepage". {"route":"app_homepage","route_parameters":{"_controller":"AppBundle\Controller\DefaultController::indexAction","_route":"app_homepage"},"request_uri":"http://localhost:8180/","method":"GET"} []
[2020-10-23 13:55:56] security.DEBUG: Read existing security token from the session. {"key":"_security_main","token_class":"Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken"} []
[2020-10-23 13:55:56] doctrine.DEBUG: SELECT [...]
[2020-10-23 13:55:56] security.DEBUG: User was reloaded from a user provider. [...]
但是当我 运行 $this->client->request('GET', '/')
时,我的 test.log 显示:
[2020-10-23 13:55:56] request.INFO: Matched route "app_homepage". {"route":"app_homepage","route_parameters":{"_controller":"AppBundle\Controller\DefaultController::indexAction","_route":"app_homepage"},"request_uri":"http://localhost","method":"GET"} []
安全无踪迹。
更新 4:另一个测试
我运行这个测试:
public function testIndex()
{
$crawler = $this->client->request('GET', '/stackTest');
$this->assertTrue($this->client->getResponse()->isSuccessful(), 'response status is 2xx');
}
在security.yml
中是这样配置的页面
firewalls:
stack:
pattern: ^/stackTest
security: false
...测试有效!
./vendor/bin/simple-phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
Testing app Test Suite
. 1 / 1 (100%)
Time: 1.08 seconds, Memory: 36.50MB
OK (1 test, 1 assertion)
我找到了!
如上所述,我的应用程序的身份验证是通过 CAS 完成的。为了测试,我想模拟这种身份验证。所以我创建了一个 FakeGuardAuthenticator,它不是询问 CAS 服务器,而是模拟它和 returns 凭据。
因此,在我的 config_test.yml 配置文件中,我必须通过别名来覆盖 guardAuthenticator。
哪个给:
# app/config/config_test.yml
imports:
- { resource: config_dev.yml }
- { resource: services_test.yml }
# app/config/service_test.yml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
app_cas.guard_authenticator:
class : Tests\AppBundle\FakeGuardAuthenticator
arguments:
# [...]
provider: cas
感谢@vstelmakh 和@Vyctorya 花时间回复我。
我在使用 symfony 3.4 进行功能测试时遇到错误已经有一段时间了。
我的应用程序 运行 自定义 GuardAuthenticator,用于在 CAS 身份验证中对我的用户进行身份验证。这只是为了解释上下文。在我的测试中,我不想使用它,我想使用特定的身份验证系统。
我写了功能测试。我用以下内容开始我的测试环境:
# app/config/config_test.yml
imports:
- { resource: config_dev.yml }
framework:
test: ~
session:
storage_id: session.storage.mock_file
name: MOCKSESSION
profiler:
collect: false
根据官方 Symfony 文档,我扩展了 symfony WebTestCase 来为我的测试设置特定的身份验证令牌 How to Simulate HTTP Authentication in a Functional Test
namespace Test\AppBunble\WebTestCase;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase as SfTestCase;
class WebTestCase extends SfTestCase
{
/**
*
* {@inheritDoc}
* @see \PHPUnit_Framework_TestCase::setUp()
*/
public function setUp()
{
$this->client = static::createClient();
$this->container = $this->client->getContainer();
$this->entityManager = $this->container->get('doctrine.orm.entity_manager');
parent::setUp();
}
public function logInAs($username)
{
$user = $this->entityManager->getRepository(User::class)->loadUserByUsername($username);
$session = $this->client->getContainer()->get('session');
$token = new PostAuthenticationGuardToken($user, 'main', $user->getRoles());
$session->set('_security_main', serialize($token));
$session->save();
$cookie = new Cookie($session->getName(), $session->getId());
$this->client->getCookieJar()->set($cookie);
}
}
最后,我写了我的(简单的)测试:
namespace Tests\AppBundle\Controller;
use Tests\AppBundle\WebTestCase;
class DefaultControllerTest extends WebTestCase
{
public function testIndex()
{
$this->logInAs('admin');
$crawler = $this->client->request('GET', '/');
$this->assertTrue($client->getResponse()->isSuccessful(), 'response status is 2xx');
}
}
我运行 phpunit :
$ ./vendor/bin/simple-phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
Testing app Test Suite
<br />
<b>Error</b>: <font color="FF0000"><b>Internal script failure</b><br />
为了调试,我修改了我的测试:
public function testIndex()
{
$this->logInAs('admin');
//$crawler = $this->client->request('GET', '/');
//$this->assertTrue($client->getResponse()->isSuccessful(), 'response status is 2xx');
}
我运行 phpunit :
./vendor/bin/simple-phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
Testing app Test Suite
. 1 / 1 (100%)
Time: 797 ms, Memory: 27.75MB
OK (1 test, 0 assertions)
经过大量测试后,我在调用测试时发现:
$this->client->request('GET', '/')
它崩溃了。
更新:另一个测试。
如果我 运行 这个 :
public function testIndex()
{
$this->logInAs('admin');
$token = $this->client->getContainer()->get('security.token_storage');
var_dump($token->getToken());
//$crawler = $this->client->request('GET', '/');
//$this->assertTrue($client->getResponse()->isSuccessful(), 'response status is 2xx');
}
它return我NULL
...没有令牌。
更新 2
我深入研究代码以返回到 symfony 停止的地方。在Symfony\Component\EventDispatcher\EventDispatcher
class.
doDispatch
方法中
它触发 `kernel.event' 事件的侦听器。当它触发名为“Symfony\Bundle\SecurityBundle\Debug\TraceableFirewallListener”的侦听器时=>“内部脚本失败”。
更新 3 如果我比较 dev.log(代表我在浏览器中 运行 应用程序时的日志),我在请求中有此日志:
[2020-10-23 13:55:56] request.INFO: Matched route "app_homepage". {"route":"app_homepage","route_parameters":{"_controller":"AppBundle\Controller\DefaultController::indexAction","_route":"app_homepage"},"request_uri":"http://localhost:8180/","method":"GET"} []
[2020-10-23 13:55:56] security.DEBUG: Read existing security token from the session. {"key":"_security_main","token_class":"Symfony\Component\Security\Guard\Token\PostAuthenticationGuardToken"} []
[2020-10-23 13:55:56] doctrine.DEBUG: SELECT [...]
[2020-10-23 13:55:56] security.DEBUG: User was reloaded from a user provider. [...]
但是当我 运行 $this->client->request('GET', '/')
时,我的 test.log 显示:
[2020-10-23 13:55:56] request.INFO: Matched route "app_homepage". {"route":"app_homepage","route_parameters":{"_controller":"AppBundle\Controller\DefaultController::indexAction","_route":"app_homepage"},"request_uri":"http://localhost","method":"GET"} []
安全无踪迹。
更新 4:另一个测试
我运行这个测试:
public function testIndex()
{
$crawler = $this->client->request('GET', '/stackTest');
$this->assertTrue($this->client->getResponse()->isSuccessful(), 'response status is 2xx');
}
在security.yml
中是这样配置的页面firewalls:
stack:
pattern: ^/stackTest
security: false
...测试有效!
./vendor/bin/simple-phpunit
PHPUnit 5.7.27 by Sebastian Bergmann and contributors.
Testing app Test Suite
. 1 / 1 (100%)
Time: 1.08 seconds, Memory: 36.50MB
OK (1 test, 1 assertion)
我找到了!
如上所述,我的应用程序的身份验证是通过 CAS 完成的。为了测试,我想模拟这种身份验证。所以我创建了一个 FakeGuardAuthenticator,它不是询问 CAS 服务器,而是模拟它和 returns 凭据。
因此,在我的 config_test.yml 配置文件中,我必须通过别名来覆盖 guardAuthenticator。
哪个给:
# app/config/config_test.yml
imports:
- { resource: config_dev.yml }
- { resource: services_test.yml }
# app/config/service_test.yml
services:
_defaults:
autowire: true
autoconfigure: true
public: false
app_cas.guard_authenticator:
class : Tests\AppBundle\FakeGuardAuthenticator
arguments:
# [...]
provider: cas
感谢@vstelmakh 和@Vyctorya 花时间回复我。