我正在尝试为Symfony系统添加登录过程的phpunit功能测试。登录过程很简单,但我在建立一个没有下面描述的许多问题之一的客户端时遇到了问题,而且我已经没有办法解决这些问题了。我对帖子的长度表示歉意。任何建议都将受到高度赞赏。
详情:
正常登录调试系统的顺序
是:
http://localhost:8000/login GET -> html form for login
http://localhost:8000/login_check POST(_username,_password) -> redirect
http://localhost:8000/useridx/NN (same as redirect)
我的测试类扩展了WebTestCase,并包含相应的公共函数:
testGetLoginPage(): tests page returned from /login, returns $context (with $client)
testLoginCheck($context): posts the login data, validates the redirect page, and returns $context (with $client)
testUserIndex($context): validates the page returned by following the redirect
当我运行测试时,testGetLoginPage成功,然后testLoginCheck得到一个带有symfony堆栈跟踪的返回页面,指示:
<title> Failed to start the session because headers have already been sent by "/home1/xxxxx-app/vendor/phpunit/phpunit/src/Util/Printer.php" at line 133. (500 Internal Server Error)</title>
使用Printer.php中的行:
print $buffer;
经过一些研究,我发现评论表明我可以通过为testLoginCheck声明这个问题来避免这个问题:
/**
* @runInSeparateProcess
*/
在声明之后,testLoginCheck获得了正确的页面(重定向)到/ useridx / NN。然后我尝试按照testUserIndex中的重定向进行操作,但是响应返回了第一个登录页面的副本,其中包含访问被拒绝的指示,即使登录测试成功。
我的下一个想法是我还需要为testUserIndex声明@runInSeparateProcess,但结果是一样的。我猜这导致了Print.php的一个进程,testLoginCheck的第二个进程,以及testUserIndex的第三个进程。我最终找到了另一个应用于我的测试类的指令:
/**
* @runTestsInSeparateProcesses
*/
我从函数中删除了@runInSeparateProcess指令。这很有效,直到其中一个测试断言失败,此时我得到一个长的symfony异常和堆栈跟踪指示:
Caused by
exception 'ErrorException' with message 'Class __PHP_Incomplete_Class has no unserializer' in /home1/xxxxx-app/vendor/phpunit/phpunit/src/Util/PHP.php:107
故意断言一次断言一个断言,我发现不完整的断言总是由第一个失败的断言触发。
与@preserveGlobalState相关的注释表明它可以被禁用以解决父进程和子进程之间的序列化/解串器问题,但为该类设置该问题会导致新问题:
RuntimeException: You must override the KernelTestCase::createKernel() method.
我还试过模拟身份验证,因此我可以使用这种方法进入剩余的测试(需要身份验证):
http://symfony.com/doc/current/testing/simulating_authentication.html
http://symfony.com/doc/current/testing/http_authentication.html
但它总是让我重定向回登录页面。
在开始使用不同的测试系统之前,我认为最好停下来寻求帮助。这是一个基本的测试,我似乎在玩傻瓜。
答案 0 :(得分:0)
我找到了似乎有用的东西,但它可能不是&#34; symfony方式&#34; ...
不要为测试类设置@runTestsInSeparateProcesses。
将login / login_check合并到一个测试中(由Massimiliano建议),这是该课程中的第一个测试,使用&#34; @ runInSeparateProcess&#34;组。然后$ client = static :: createClient(); $ context [&#34; client&#34;] = $ client; return $ context;
在所有后续测试中,$ client = $ context [&#34; client&#34;];在进入,并返回$ context。 不为剩余的测试设置@runInSeparateProcess。使用此方法根据需要包含尽可能多的testXxx函数。客户端已经登录,因此权限没有问题。
我曾尝试将一个安全/防火墙/测试/ http_basic规则添加到app / config / security.yml,但它对我的系统授权方式并不起作用,并且所有后续操作都是由于权限问题,测试失败。
&#34;类__PHP_Incomplete_Class没有反序列化器&#34;当测试以&#34; bin / phpunit -c app src / BundleXxx / Tests / Controller / TheTest.php&#34;运行时,异常仍然是一个问题,但是当它作为一部分运行时不会发生&#34; bin / phpunit -c app&#34;。我可以忍受这种情况,并且我已经为此添加了文档。