Symfony2& PHPUnit - 访问getContainer()

时间:2015-06-18 15:41:09

标签: php symfony login parameters phpunit

我在Symfony2上的PHPUnit测试有问题。要连接到我的应用程序,我使用Web服务,因此我创建了一个UserProvider。在我的函数for (i in letters) { for (j in variables) { # create all lags mst_ij <- macro.set.ts[[i]][,j] jL <- merge(lag(mst_ij), lag(mst_ij, 2), lag(mst_ij, 4)) colnames(jL) <- paste(j, c("L1","L2","L4"), sep="_") # merge back with original data macro.set.ts[[i]] <- merge(macro.set.ts[[i]], jL) } } 中,我使用保存在loadUserByUsername中的Symfony2参数。由于我不在控制器中,我需要使用全局变量app/config/parameters.yml并得到我的args:

$kernel

当我使用我的应用程序时,它可以工作,但是当我像这样编写测试时:

global $kernel;

$url = $kernel->getContainer()-getParameter('myparam');

并执行PHPUnit我收到此错误:

  

致命错误:调用成员函数getContainer()

如何在执行PHPUnit时访问Symfony2参数或使用$crawler = $client->request('GET', '/login'); $form = $crawler->selectButton('submit')->form(); $form['_username'] = $username; $form['_password'] = $pass;

2 个答案:

答案 0 :(得分:2)

在Symfony文档How to Create a custom UserProvider中,在“为用户提供商创建服务”下,它指出:

  

用户提供商的真正实现可能会有一些   依赖项或配置选项或其他服务。将这些添加为   服务定义中的参数。

因此,您应该通过将相关参数定义为服务定义中的参数,而不是使用全局$内核变量来将相关参数传递到用户提供程序服务中。例如:

services:
    webservice_user_provider:
        class: Acme\WebserviceUserBundle\Security\User\WebserviceUserProvider
        arguments: [%parameter_one%, %parameter_two%, ...]

与任何服务一样,您的用户提供者服务类必须具有一个构造函数,该构造函数接受与服务定义中的参数相对应的参数,并将它们存储在私有变量中,以便在服务的方法中使用:

class WebserviceUserProvider implements UserProviderInterface
{
    private parameterOne;
    ...

    public function __construct($parameterOne, ...)
    {
        $this->parameterOne = $parameterOne;
        ...
    }
    ...
}

我已经编写了四年的Symfony应用程序,我永远不需要使用全局$ kernel变量。我敢说有可能是有效的情况,但总的来说我会说应该避免。

答案 1 :(得分:1)

首先,您不应使用global关键字访问内核。您始终可以将其作为依赖项(即@kernel)注入。如果您的目标只是访问容器,那么您应该只注入@service_container的服务容器。正确和最好的方法是只注入像redbirdo建议的参数(即%parameter_one%%parameter_two%)。

关于您的测试,您应该创建并启动推进内核以便能够使用它。

我建议您创建一个KernelTestCase类,以便您的测试可以扩展它并访问容器以及您在控制器中执行的所有操作。

<?php

namespace AppBundle\Tests;

use Symfony\Bundle\FrameworkBundle\Test\KernelTestCase as TestCase;

/**
 * Class KernelTestCase
 * @package AppBundle\Tests
 * @author Francesco Casula <fra.casula@gmail.com>
 */
abstract class KernelTestCase extends TestCase
{
    /**
     * @var \Symfony\Component\DependencyInjection\ContainerInterface
     */
    private $container;

    /**
     * {@inheritdoc}
     */
    public function tearDown()
    {
        $this->container = null;
        parent::tearDown();
    }

    /**
     * @param array $options
     * @return \Symfony\Component\DependencyInjection\ContainerInterface
     */
    protected function getContainer(array $options = [])
    {
        if (!$this->container) {
            static::bootKernel($options);
            $this->container = static::$kernel->getContainer();
        }

        return $this->container;
    }

    /**
     * @param string $parameter
     * @return mixed
     */
    protected function getParameter($parameter)
    {
        return $this->getContainer()->getParameter($parameter);
    }
}

然后在你的考试班......

<?php

namespace AppBundle\Tests\IntegrationTests;

use AppBundle\Tests\KernelTestCase as TestCase;

/**
 * Class ExampleTest
 * @package AppBundle\Tests\IntegrationTests
 * @author Francesco Casula <fra.casula@gmail.com>
 */
class ExampleTest extends TestCase
{
    public function testMyMethod()
    {
        $parameter = $this->getParameter('whatever');

        // ...

        $service = $this->getContainer()->get('service');
    }
}