Symfony2功能测试和会话持久性

时间:2016-07-26 12:41:06

标签: php symfony session testing functional-testing

这是我的问题,我从功能测试控制器添加会话变量,他们不会弹出测试所针对的操作。

我创建了一个登录方法并使用cookbook advice登录。我调整了一下以允许2个帐户登录:admin和superadmin

import { Injectable } from '@angular/core';

我的setUp()方法执行此操作:

/**
     * @param $account string the account to log in with (authorized : superadmin and admin)
     */
    protected function logIn($account)
    {
        $this->session = $this->container->get('session');
        // Cookbook try
        // $this->session = new Session(new MockFileSessionStorage());
        $user = $this->em->getRepository('LCHUserBundle:User')->findOneByUsername($account);
        $firewall = 'admin_area';

        switch($account) {
            case self::SUPER_ADMIN_LOGIN:
                $token = new UsernamePasswordToken($user, $account, $firewall, array('ROLE_SUPER_ADMIN'));
                $this->client->setServerParameter("SERVER_NAME", SiteControllerTest::ROOT_SITE);
                $this->client->setServerParameter("HTTP_HOST", SiteControllerTest::ROOT_SITE);
                break;
            case self::ADMIN_LOGIN:
                $token = new UsernamePasswordToken($user, $account, $firewall, array('ROLE_ADMIN'));

                // Session var I wish to have on my controller action tested
                $this->session->set('currentSite', $this->em->getRepository('LCHMultisiteBundle:Site')->find(1));
                $this->session->save();

                // Use to force server canonical name for admin test
                $this->client->setServerParameter("SERVER_NAME", SiteControllerTest::ROOT_SITE);
                $this->client->setServerParameter("HTTP_HOST", SiteControllerTest::TEST_SITE);
                break;
            default:
                throw new UsernameNotFoundException('Username provided doesn\'t match any authorized account');
        }
        // Save user in session
        $this->session->set('_security_'.$firewall, serialize($token));
        $this->session->set('user', $user);
        $this->session->save();
        // $this->container->set('session', $this->session);

        $cookie = new Cookie($this->session->getName(), $this->session->getId());
        $this->client->getCookieJar()->set($cookie);

您可以看到我设置会话变量进行身份验证。当我从测试的操作转储会话var时它们正确显示,但如果我添加我的currentSite会话var,它似乎不会持久化。当我使用客户提供的测试容器时,它应该传递给它吗?

PS:根据this other question,我也覆盖了客户端类。

我发现了很多关于主题的帖子,但没有提供任何可行的解决方案(this onethis onethat one)。 我也发现了cookbook article

更新:感谢Alex Blex的评论,我在这里澄清了我的一些问题。

  • setUp()和logIn()都是自定义WebTestCase类的一部分,嵌入我的应用程序特性所需的工具(例如翻译器......)
  • 我的主要观点是在测试控制器中设置会话参数并在测试的操作中检索这些会话参数

1 个答案:

答案 0 :(得分:0)

目前尚不清楚您的测试内容,您的期望以及失败的地方。添加实际测试是有意义的。为什么在测试中你需要容器​​,翻译器等?

会议没有什么特别需要做的事情。考虑这个示例控制器,它在会话中保持'test'的值并在连续调用时递增它:

/**
 * @Route("/session")
 * @Method({"GET"})
 */
public function session()
{
    $session = $this->container->get('session');
    $current = $session->get('test', 0);
    $session->set('test', $current + 1);
    return new Response($current);
}

此测试通过:

/**
 * @test
 */
public function session_increments()
{
    $client = static::createClient();        
    $client->request("GET", '/session');
    $this->assertEquals('0', $client->getResponse()->getContent());
    $client->request("GET", '/session');
    $this->assertEquals('1', $client->getResponse()->getContent());
}

您的应用程序逻辑可能更复杂,但测试应该保持相同 - 首先调用登录,第二次调用断言响应包含登录用户独有的内容。

<强>更新

尽可能避免在功能测试中使用内部实现,但对于某些边缘情况可能是必不可少的,例如:简化测试方案。

以下示例通过在测试场景中为会话变量设置特定值来测试同一个控制器,并检查应用程序返回的值:

/**
 * @test
 */
public function session_returns_value()
{
    $client = static::createClient();        
    $session = $client->getContainer()->get('session');
    $session->set('test', 12);
    $client->request("GET", '/session');
    $this->assertEquals('12', $client->getResponse()->getContent());
}