5

尝试在实现会话的控制器方法上运行基于控制器的单元测试时遇到问题。

在这种情况下,这里是控制器方法:

/**
 * @Route("/api/logout")
 */
public function logoutAction()
{
    $session = new Session();
    $session->clear();

    return $this->render('PassportApiBundle:Login:logout.html.twig');
}

和功能测试:

public function testLogout()
{
    $client = static::createClient();
    $crawler = $client->request('GET', '/api/logout');
    $this->assertTrue($client->getResponse()->isSuccessful());
}

产生的错误:

无法启动会话,因为标头已发送。(500内部服务器错误)

我试过$this->app['session.test'] = true;参加测试,但还是不行。有没有人尝试解决这样的问题来对使用会话的控制器进行单元测试?

4

3 回答 3

13

首先,您应该使用容器中的会话对象。所以你的动作应该更像:

/**
 * @Route("/api/logout")
 */
public function logoutAction()
{
    $session = $this->get('session');
    $session->clear();

    return $this->render('PassportApiBundle:Login:logout.html.twig');
}

然后在您的测试中,您可以将服务注入“客户的容器”。所以:

public function testLogout()
{
    $sessionMock = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session')
        ->setMethods(array('clear'))
        ->disableOriginalConstructor()
        ->getMock();

    // example assertion:
    $sessionMock->expects($this->once())
        ->method('clear');

    $client = static::createClient();
    $container = $client->getContainer();
    $container->set('session', $sessionMock);

    $crawler = $client->request('GET', '/api/logout');
    $this->assertTrue($client->getResponse()->isSuccessful());
}

使用此代码,您可以使用会话服务做任何您想做的事情。但是你必须知道两件事:

  • 这个模拟将只为一个请求设置(如果你想在下一个请求中使用它,你应该重新设置它)。这是因为客户端在每个请求之间重新启动内核并重建容器。
  • Symfony 2.1 中的会话处理与 Symfony 2 略有不同

编辑:

我添加了一个断言

于 2012-12-04T08:11:22.820 回答
8

就我而言,设置就足够了

framework:
    session:
        storage_id: session.storage.mock_file

config_test.yml. YMMV,我对我实际上在做什么并没有太多了解,但它对我有用。

于 2014-01-31T17:38:37.230 回答
2

这里只是为了完成 Cyprian 的回复。

正如 Sven 解释的那样,在查看 symfony 的文档http://symfony.com/doc/2.3/components/http_foundation/session_testing.html时,您必须使用 MockFileSessionStorage 对象作为第一个构造函数参数来实例化模拟会话。

您需要使用:

    use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage;

代码应该是:

    $sessionMock = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')
        ->setMethods(array('clear'))
        ->disableOriginalConstructor()
        ->setConstructorArgs(array(new MockFileSessionStorage()))
        ->getMock();
于 2013-12-30T14:59:53.883 回答