使用需要发送标头的项目进行单元测试

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)

  • 测试黑盒PHP代码的最佳解决方案,你无法改变. (2认同)
  • 这个解决方案对我有用:D PHPUnit 3.6应该实现这个但是对我来说不能正常工作.我添加了ob_start(); 进入我的bootstrap.php文件,我的所有测试与cookie和标题再次开始正常工作. (2认同)

Jua*_*che 13

我有同样的问题,我通过使用--stderr标志调用phpunit来解决它,就像这样:

phpunit --stderr /path/to/your/test
Run Code Online (Sandbox Code Playgroud)

希望它可以帮到某人!


Kor*_*nel 5

我认为"正确"的解决方案是创建一个非常简单的类(这么简单,不需要测试),这是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)