session之使用 Silex SessionServiceProvider 时 PHPUnit 失败

Renyi-Fan 阅读:41 2024-11-01 17:39:52 评论:0

我正在尝试为我的 Silex 应用程序创建单元测试。单元测试类看起来像这样:

class PageTest extends WebTestCase { 
 
    public function createApplication() { 
        $app = require __DIR__ . '/../../app/app.php'; 
        $app['debug'] = true; 
 
        $app['session.storage'] = $app->share(function() { 
            return new MockArraySessionStorage(); 
        }); 
 
        $app['session.test'] = true; 
 
        unset($app['exception_handler']); 
        return $app; 
    } 
 
    public function testIndex() { 
        $client = $this->createClient(); 
        $client->request('GET', '/'); 
        $this->assertTrue($client->getResponse()->isOk()); 
    } 
 
} 

它尝试请求的 silex 路由看起来像这样:

$app->get('/', function() use($app) { 
    $user     = $app['session']->get('loginUser'); 
 
    return $app['twig']->render('views/index.twig', array( 
        'user'           => $user, 
    )); 
}); 

这会导致 RuntimeException: Failed to start the session because headers have been sent.\Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage.php:142 回溯包含来自 $app['session']->get 的路由行。

看起来在 NativeSessionStorage 中尝试启动 session 之前发生的输出实际上是 PHPUnit 输出信息,因为这是我在错误消息之前得到的唯一输出:

PHPUnit 3.7.8 by Sebastian Bergmann. 
 
Configuration read from (PATH)\phpunit.xml 
 
E....... 

我有点困惑,因为 phpunit 的这个错误输出发生在实际测试方法执行之前的输出中。我没有运行任何其他测试方法,所以它必须来自这个错误。

我应该如何让 PHPUnit 在使用 session 变量的 silex 路由上工作?

请您参考如下方法:

在下方评论后编辑

好的,我遇到了同样的问题,浏览网页一个小时后,我设法通过了测试。

在 Silex 2.0-dev 上,从 WebTestCase 类调用 $app['session.test'] = true 根本不起作用,它需要发生在 Bootstrap 中。

实现它的方法有很多,这里是其中的两个:

1/与 phpunit.xml.dist

<?xml version="1.0" encoding="UTF-8"?> 
<phpunit backupGlobals="false" 
     backupStaticAttributes="false" 
     colors="true" 
     convertErrorsToExceptions="true" 
     convertNoticesToExceptions="true" 
     convertWarningsToExceptions="true" 
     processIsolation="false" 
     stopOnFailure="false" 
     syntaxCheck="false" 
     bootstrap="./app.php" 
> 
    <php> 
        <env name="TEST" value="true" />          //-> This is the trick 
    </php> 
    <testsuites> 
        <testsuite name="Your app Test Suite"> 
            <directory>./tests/</directory> 
        </testsuite> 
    </testsuites> 
</phpunit> 

然后在 Bootstrap 中

$app = new \Silex\Application(); 
 
... 
 
$app->register(new \Silex\Provider\SessionServiceProvider(), [ 
    'session.test' => false !== getenv('TEST') 
]); 
 
... 
 
return $app; 


2/通过扩展 Silex\Application 以便您可以将环境传递给构造函数

namespace Your\Namespace; 
 
class YourApp extends \Silex\Application 
{ 
    public function __construct($env, array $params = array()) 
    { 
        $this['env'] = $env; 
 
        parent::__construct($params); 
    } 
} 

然后在你的 Bootstrap 中

$env = // Your logic ... 
 
$app = new \Your\Namespace\YourApp($env); 
 
... 
 
$app->register(new \Silex\Provider\SessionServiceProvider(), [ 
    'session.test' => 'test' === $app['env'], 
]); 
 
... 
 
return $app; 

希望对您有所帮助,干杯!


标签:PHP
声明

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

关注我们

一个IT知识分享的公众号