Mez*_*Mez 47 php phpunit unit-testing
我目前正在使用PHPUnit来尝试和我正在编写的内容一起开发测试,但是,我正在编写会话管理器,并且遇到了这样的问题......
Session处理类的构造函数是
private function __construct()
{
if (!headers_sent())
{
session_start();
self::$session_id = session_id();
}
}
Run Code Online (Sandbox Code Playgroud)
但是,由于PHPUnit在开始测试之前发送文本,因此对此Object的任何测试都会返回失败的测试,因为HTTP"Headers"已经发送...
tro*_*skn 36
好吧,您的会话管理器基本上是按设计破解的.为了能够测试某些东西,必须能够将其与副作用隔离开来.不幸的是,PHP被设计以这样一种方式,它鼓励自由使用全局状态(echo,header,exit,session_start等等,等等).
您可以做的最好的事情是隔离组件中的副作用,这些副作用可以在运行时交换.这样,您的测试可以使用模拟对象,而实时代码使用具有真正副作用的适配器.你会发现这对单身人士来说效果不佳,我猜你正在使用它.因此,您必须使用其他一些机制来获取分配给代码的共享对象.您可以从静态注册表开始,但如果您不介意一点学习,还有更好的解决方案.
如果你不能这样做,你总是可以选择编写集成测试.例如.使用PHPUnit的等价物WebTestCase.
小智 20
为phpunit创建一个bootstrap文件,调用:
session_start();
Run Code Online (Sandbox Code Playgroud)
然后像这样启动phpunit:
phpunit --bootstrap pathToBootstrap.php --anotherSwitch /your/test/path/
Run Code Online (Sandbox Code Playgroud)
引导文件在其他所有内容之前被调用,因此标头尚未发送,一切都应该正常工作.
小智 19
phpUnit在测试运行时输出输出,因此即使在第一次测试中,headers_sent()也会返回true.
要解决整个测试套件的这个问题,您只需在设置脚本中使用ob_start()即可.
例如,假设你有一个名为AllTests.php的文件,这是phpUnit加载的第一件事.该脚本可能如下所示:
<?php
ob_start();
require_once 'YourFramework/AllTests.php';
class AllTests {
public static function suite() {
$suite = new PHPUnit_Framework_TestSuite('YourFramework');
$suite->addTest(YourFramework_AllTests::suite());
return $suite;
}
}
Run Code Online (Sandbox Code Playgroud)
Jua*_*che 13
我有同样的问题,我通过使用--stderr标志调用phpunit来解决它,就像这样:
phpunit --stderr /path/to/your/test
Run Code Online (Sandbox Code Playgroud)
希望它可以帮到某人!
我认为"正确"的解决方案是创建一个非常简单的类(这么简单,不需要测试),这是PHP的会话相关函数的包装,并使用它而不是session_start()直接调用等.
在测试中传递模拟对象而不是真正有状态的,不可测试的会话类.
private function __construct(SessionWrapper $wrapper)
{
if (!$wrapper->headers_sent())
{
$wrapper->session_start();
$this->session_id = $wrapper->session_id();
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
20037 次 |
| 最近记录: |