Symfony 3.4无法在测试中加载灯具:错误:在null上调用成员函数get()

时间:2018-07-23 11:52:53

标签: php symfony doctrine phpunit symfony-3.4

我有以下用于测试控制器的phpunit测试:

DefaultControllerTest

namespace Tests\AppBundle\Controller;

use Tests\AppBundle\Controller\BasicHttpController;
use AppBundle\DataFixtures\Test\DummyUserFixtures;

/**
* @testtype Functional
*/
class DefaultControllerTest extends BasicHttpController
{
    /**
    * {@inheritdoc}
    */
    public function setUp()
    {
        $fixture = new DummyUserFixtures();
        $fixture->load($this->entityManager);
    }

    /**
    * Testing the Behavior when visiting the index page
    */
    public function testIndex()
    {
        $client = $this->client;
        $router=$client->getContainer()->get('router');
        $crawler = $client->request('GET', '/');
        $response=$client->getResponse();
        $this->assertTrue($client->getResponse()->isRedirect());
        $this->assertEquals($router->getRouteCollection()->get('fos_user_security_login')->getPath(),$response->headers->get('Location'));

        //@todo Create Dummy Users
        // $this->checkPanelAfterSucessfullLogin($crawler);
    }
}

这扩展了以下测试BasicHttpController(尝试应用DRY原理):

namespace Tests\AppBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
use Doctrine\Common\DataFixtures\Purger\ORMPurger;

class BasicHttpController extends WebTestCase
{
    protected $entityManager=null;

    protected $client=null;

    /**
    * {@inheritdoc}
    */
    public function __construct()
    {
        parent::__construct();
        $this->client = static::createClient();
        $container = $this->client->getContainer();
        $doctrine = $container->get('doctrine');
        $this->entityManager=$doctrine->getManager();
    }

    /**
    * Remove all entities from the database
    */
    protected function truncateEntities()
    {
        $purger = new ORMPurger($this->entityManager());
        $purger->purge();
    }


    /**
    * {@inheritdoc}
    */
    public function tearDown()
    {
        $this->truncateEntities();
    }

    /**
    * @param username String the user's username
    * @param passwoρd String the user's password
    */
    protected function checkPanelAfterSucessfullLogin($crawler,string $username,string $password)
    {
        //Submitting the form
        $form=$crawler->selectButton('_submit')->form();
        $form['_username']=$username;
        $form['_password']=$password;

        $crawler=$crawler->submit($form);
        $response=$client->getResponse();
        $this->assertTrue($client->getResponse()->isRedirect());
        $client->followRedirect();

        //Checking header
        $headerDom=$crawler->filter('header')->childen()->filter('nav.navbar')->children();
        $this->assertCount(1,$headerDom->find('a.navbar-brand')); //homepage link
        $this->assertCount(1,$headerDom->find('a.btn-danger')); //Logout button
    }
}

如您所见,我尝试加载以下灯具:

namespace AppBundle\DataFixtures\Test;

use Doctrine\Common\DataFixtures\AbstractFixture;
use Doctrine\Common\DataFixtures\OrderedFixtureInterface;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Doctrine\Common\Persistence\ObjectManager;

class DummyUserFixtures extends AbstractFixture implements OrderedFixtureInterface,ContainerAwareInterface
{

    /**
    * @var ContainerInterface
    */
    private $container=null;


    /**
    * {@inheritDoc}
    */
    public function setContainer(ContainerInterface $container = null)
    {
        $this->container = $container;
    }

    /**
    * Generic function that creates a user with provided information.
    * @param $name {String} The user's name
    * @param $surname {String} The user's surname
    * @param $username {String} The user's username
    * @param $password {String} The user's password
    * @param $email {String} The user's recovery email
    * @param $role {String} The user's system role
    * @param $phone {String | null} The user's phone number
    * @param $organization {String|null} The user's organization
    * @param $occupation {String|null} The user's occupation
    *
    * @return AppBundle\Entity\User
    */
    private function createUser($name,$surname,$username,$password,$email,$role,$phone=null,$organization=null,$occupation=null)
    {
        $fosUserManager=$this->container->get('fos_user.user_manager');

        /**
        * @var AppBundle\Entity\User
        */
        $user=$fosUserManager->createUser();
        $user->setUsername($username);
        $user->setEmail($email);
        $user->setPlainPassword($password);
        $user->setEnabled(true);
        $user->setRoles(array($role));

        $user->setName($name);
        $user->setSurname($surname);

        if($phone){
            $user->setPhone($phone);
        }

        if($organization){
            $user->setOrganization($organization);
        }

        if($occupation){
            $user->setOccupation($occupation);
        }

        $fosUserManager->updateUser($user, true);

        return $user;
    }

    /**
    * {@inheritDoc}
    */
    public function load(ObjectManager $manager)
    {
        $this->createUser('John','Doe','jdoe','simplepasswd','jdoe@example.com','ROLE_USER','+3021456742324','Acme Products','Soft Engineer');
        $this->createUser('Jackie','Chan','jchan','thesimplepasswd','jackiechan@example.com','ROLE_ADMIN','+302141232324','Holywood','Actor');
        $this->createUser('Chuck','Norris','chuck_norris','unhackablepasswd','chucknorris@example.com','ROLE_SUPERADMIN',null,'Universe','Master');
    }

    public function getOrder()
    {
       return 1;
    }
}

但是由于某些原因,我收到以下错误消息:

  

有1个错误:

     

1)测试\ AppBundle \ Controller \ DefaultControllerTest :: testIndex   错误:在null上调用成员函数get()

     

/home/vagrant/code/src/AppBundle/DataFixtures/Test/DummyUserFixtures.php:50   /home/vagrant/code/src/AppBundle/DataFixtures/Test/DummyUserFixtures.php:87   /home/vagrant/code/tests/AppBundle/Controller/DefaultControllerTest.php:19

进一步的调试已证明该错误是由DummyUserFixtures中的以下行触发的:

    $fosUserManager=$this->container->get('fos_user.user_manager');

那么您知道如何通过固定装置加载数据吗?

1 个答案:

答案 0 :(得分:0)

为了使其正常工作,您应该设置通过static::createClient()方法生成的服务容器,并将其通过$fixture->setContainer($container)

传递

因此,一种好的方法是将容器定义为BasicHttpController的受保护实例变量,以便任何Test类(例如您的案例中的DefaultControllerTest)都能够相应地加载灯具。

因此,使用setUp方法和BasicHttpController的实例变量应为:

//Namespace declaration goes there

class BasicHttpController extends WebTestCase
{
    protected $entityManager=null;

    protected $client=null;

    protected $container=null;

    /**
    * {@inheritdoc}
    */
    public function setUp()
    {
        $this->client = static::createClient();
        $this->container = $this->client->getContainer();
        $doctrine = $this->container->get('doctrine');
        $this->entityManager=$doctrine->getManager();
    }

    // Rest methods here
}

注意:在从BasicHttpController继承的类上,您可以这样定义setUp

public function setUp()
{
   parent::setUp();
   // Add extra stuff here
}

因此,您可以在测试之前进行更多的设置启​​动。