我有以下情况。我们说我有两个班级:
class Session {
public function start() {
return session_start();
}
// methods for all the other session functions of PHP
}
扩展Session
class TrustedSession extends Session {
public function start() {
if(parent::start() === false)
return false;
$requestRemoteAddress = isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:null;
$requestUserAgent = isset($_SERVER['HTTP_USER_AGENT'])?$_SERVER['HTTP_USER_AGENT']:null;
$trustedRemoteAddress = $this->get('TRUSTED_REMOTE_ADDR');
$prevUserAgent = $this->get('PREV_USERAGENT');
if($trustedRemoteAddress !== $requestRemoteAddress || $prevUserAgent !== $requestUserAgent)
$this->regenerateID(true);
return true;
}
}
所以我不想测试我的TrustedSession
课程。但是我必须使用Session
的模拟因为according to this question here我不能使用PHP的真实会话函数,因为它们会导致PHPUnit出现Output already started
错误。
现在的问题是:如何模拟Session
课程。我的意思是我可以创建一个SessionInterface
来定义我必须为Session
实现的方法及其模型。但是,如何使用模型扩展我的TrustedSession
类?
我的想法是在运行时交换父类,但我认为这是不可能的(至少在PHP中)。这是一个设计问题,我正在思考上面描述的界面,但这并没有帮助我摆脱这种情况。有没有"清洁"和好的解决方案?
答案 0 :(得分:0)
定义接口并使Session成为TrustedSession的依赖项:
interface ISession
{
public function start();
}
class Session implements ISession
{
public function start()
{
return session_start();
}
}
class TrustedSession implements ISession
{
private $session;
public function __construct(Session $session)
{
$this->session = $session;
}
public function start()
{
if (!$this->session->start()) {
return false;
}
$requestRemoteAddress = isset($_SERVER['REMOTE_ADDR'])?$_SERVER['REMOTE_ADDR']:null;
....
return true;
}
}
这样,您可以在测试TrustedSession时注入Session Mock
答案 1 :(得分:-1)
我自己回答这个问题,因为当我使用PHPUnit与向客户端发送标头的PHP函数(如Output already started
那样)进行测试时,我有办法解决这个问题session_start()
。
它非常简单,但也非常hacky,肯定是不洁净的。我所做的是使用phpunit.xml
选项来执行引导程序文件。
<phpunit bootstrap="bootstrap.php" colors="true">
<!-- testsuites here -->
</phpunit>
在bootstrap.php
文件中我放了这些代码行:
ob_start();
// Composer autoload file
require '../vendor/autoload.php';
现在,PHPUnit发送给客户端的所有输出都会被缓存,直到脚本结束。这适用于版本3.7.*
中的PHPUnit。我还没有使用版本4.x
对其进行测试,因为我使用PHPStorm进行开发。
这也仅适用于标准单元测试,并且由于代码覆盖模块中的某处被强制清理并发送给客户端而无法进行代码覆盖。我在bootstrap.php
文件中开始的输出缓冲。