【问题标题】:PHPUnit web test error while sending headers in the test在测试中发送标头时 PHPUnit web 测试错误
【发布时间】:2018-02-26 13:28:47
【问题描述】:

我在 symfony 中编写了一个 REST API。它接受 Json 请求并生成带有 FPDF library 的格式化 pdf 作为响应。

我想写一个 phpunit 网络测试来检查响应状态和标头数据。

public function test_getCertificate()
{
    $client = $this->getClient(['username'=>'user','password'=>'xxxxxx']);

    $client->request(
        'GET',
        '/api/v1/certificate',
        array(),
        array(),
        array('CONTENT_TYPE' => 'application/json'),
        null
    );

    $this->assertEquals(200, $client->getResponse()->getStatusCode());

    $this->assertTrue(
        $client->getResponse()->headers->contains(
            'Content-Type',
            'application/x-download'
        )
    );

    $this->assertTrue(
        $client->getResponse()->headers->contains(
            'Content-Disposition',
            'attachment; filename="el_certificate.pdf"'
        )
    );
}

问题是当运行测试时,PHPUnit 已经开始输出标题,然后我的控制器有问题生成 PDF:

Uncaught PHP Exception Exception: "FPDF error: Some data has already been output, can't send PDF file"

header() 由我无法修改的库代码调用。当我尝试使用 ob_end_clean() 清理测试脚本中的输出缓冲区或使用 ob_start() 启动新缓冲区时出现异常:

Uncaught PHP Exception PHPUnit_Framework_Error_Warning: "Cannot modify header information - headers already sent by (output started at /usr/share/php/PHPUnit/Util/Printer.php:134)"

版本PHP 7.2.2-3+ubuntu16.04.1+deb.sury.org+1PHPUnit 5.1.3

对如何处理这种情况有什么建议吗?

编辑: 我尝试在单独的进程中运行此测试:

/**
 * @runInSeparateProcess
 * @preserveGlobalState disabled
 */
public function test_getCertificate()
{
    //...
}

然后,我得到了错误:

PHP Warning:  Uncaught require_once(/var/cache/test/jms_diextra/doctrine/EntityManager_5a9419b75e6b1.php): failed to open stream: No such file or directory

/vendor/symfony/phpunit-bridge/DeprecationErrorHandler.php:108
/var/cache/test/appTestDebugProjectContainer.php:2456
/var/cache/test/appTestDebugProjectContainer.php:2456
/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:329
/var/cache/test/appTestDebugProjectContainer.php:8179
/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:329
/var/cache/test/appTestDebugProjectContainer.php:7994
/vendor/symfony/symfony/src/Symfony/Component/DependencyInjection/Container.php:329
/var/cache/test/appTestDebugProjectContainer.php:7954
/var/www/html/elearning-ap in /var/cache/test/appTestDebugProjectContainer.php on line 2456
PHP Fatal error:  appTestDebugProjectContainer::getDoctrine_Orm_DefaultEntityManagerService(): Failed opening required '/var/cache/test/jms_diextra/doctrine/EntityManager_5a9419b75e6b1.php' (include_path='.:/usr/share/php') in /var/cache/test/appTestDebugProjectContainer.php on line 2456
test_getPhases
{"error":{"code":500,"message":"Internal Server Error","exception":[{"message":"Compile Error: appTestDebugProjectContainer::getDoctrine_Orm_DefaultEntityManagerService(): Failed opening required '\/var\/cache\/test\/jms_diextra\/doctrine\/EntityManager_5a9419b75e6b1.php' (include_path='.:\/usr\/share\/php')","class":"Symfony\\Component\\Debug\\Exception\\FatalErrorException","trace":[{"namespace":"","short_class":"","class":"","type":"","function":"","file":"\/var\/cache\/test\/appTestDebugProjectContainer.php","line":2456,"args":[]}]}]}}

【问题讨论】:

    标签: php rest symfony phpunit


    【解决方案1】:

    好吧,我终于弄清楚发生了什么。

    如果 PHPUnit 应该测试一些发出标头的代码(例如生成文件),那么测试应该在一个单独的进程中运行。这可以实现using annotation

    /**
     * @runInSeparateProcess
     * @preserveGlobalState disabled
     */
    public function test_getCertificate()
    {
        //...
    }
    

    在我的例子中,JMSDiExtraBundle 产生了错误,因为将它包装在它自己的代理对象中。如果不想让 JMSDiExtra 为学说生成代理类那么可以添加如下配置:

    jms_di_extra:
        doctrine_integration: false
    

    之后,测试可以在单独的进程中正常运行,而不会出现标题输出问题。

    【讨论】:

      猜你喜欢
      • 2012-12-18
      • 2012-04-02
      • 1970-01-01
      • 2016-06-04
      • 2015-01-14
      • 1970-01-01
      • 1970-01-01
      • 2010-11-14
      • 1970-01-01
      相关资源
      最近更新 更多