代码之家  ›  专栏  ›  技术社区  ›  Dimitrios Desyllas

symfony 3.4无法在测试时加载设备:错误:对空的成员函数get()的调用

  •  0
  • Dimitrios Desyllas  · 技术社区  · 7 年前

    我对控制器进行了以下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 (尽量采用干法原理):

    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 错误:在空值上调用成员函数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 回复  |  直到 7 年前
        1
  •  0
  •   Dimitrios Desyllas    7 年前

    为了使其正常工作,您应该设置从 static::createClient() 方法并通过 $fixture->setContainer($container)

    因此,一个好的方法是将容器定义为 BasicHttpController 所以任何测试类(如 DefaultControllerTest 在您的情况下)能够相应地加载夹具。

    所以使用 setUp 方法和实例变量 basichttp控制器 应该是以下内容:

    //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
    }
    

    注: 继承自的类 basichttp控制器 您可以定义 设置 就像这样:

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

    所以您可以在测试之前进行更多的设置引导。

    推荐文章