如何在PHPUnit测试用例中使用服务器变量?

如何在PHPUnit测试用例中使用服务器变量?,php,symfony,phpunit,Php,Symfony,Phpunit,我正在使用PHPUnit测试用例测试模块。一切正常,但当我使用$\u SERVER['REMOTE\u ADDR']时,它会出现致命错误并停止执行 CategoryControllerTest.php <?php namespace ProductBundle\Controller\Tests\Controller; use Symfony\Bundle\FrameworkBundle\Test\WebTestCase; class CategoryControllerTest exten

我正在使用PHPUnit测试用例测试模块。一切正常,但当我使用
$\u SERVER['REMOTE\u ADDR']
时,它会出现致命错误并停止执行

CategoryControllerTest.php

<?php
namespace ProductBundle\Controller\Tests\Controller;
use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
class CategoryControllerTest extends WebTestCase {

     protected function setUp() {
        static::$kernel = static::createKernel();
        static::$kernel->boot();
        $this->container = static::$kernel->getContainer();
        $this->em = static::$kernel->getContainer()->get('doctrine')->getManager();
    }

    public function testCategory() {
        $ip_address = $_SERVER['REMOTE_ADDR'];
        $client = static::createClient(
          array(), array('HTTP_HOST' => static::$kernel->getContainer()->getParameter('test_http_host')
        ));

        $crawler = $client->request('POST', '/category/new');
        $client->enableProfiler();

        $this->assertEquals('ProductBundle\Controller\CategoryController::addAction', $client->getRequest()->attributes->get('_controller'));
        $form = $crawler->selectButton('new_category')->form();
        $form['category[name]'] = "Electronics";
        $form['category[id]']   = "For US";
        $form['category[ip]']   = $ip_address;
        $client->submit($form);

        $this->assertTrue($client->getResponse()->isRedirect('/category/new')); // check if redirecting properly
        $client->followRedirect();
        $this->assertEquals(1, $crawler->filter('html:contains("Category Created Successfully.")')->count());
    }
}
class UserIpAddressController
{
  public function get()
  {
    return $_SERVER['REMOTE_ADDR'];
  }
}
$UserIpAddress = $this->getMockBuilder('UserIpAddress')
    ->disableOriginalConstructor()
    ->getMock();

$UserIpAddress->expects($this->once())
  ->method('get')
  ->willReturn('192.161.1.1'); // Set ip address whatever you want to use

从技术上讲,您尚未向应用程序发送请求,因此没有可参考的远程地址。事实上,这也是你的错误告诉我们的

要解决此问题,请执行以下操作:

  • 将行移到下面:

    // Won't work, see comment below    
    $crawler = $client->request('POST', '/category/new');
    
  • 或者你可以编一个IP地址并用它进行测试。由于您只使用IP来保存模型,因此也可以这样做


  • 就像评论中提到的@apokryfos一样,在测试用例中访问超全局被认为是不好的做法。因此,选项2可能是您在这里的最佳选择。

    创建返回ip地址的服务,并在测试用例中模拟该服务

    在这里,将控制器和服务创建为UserIpAddress
    get()
    将返回用户的ip地址

    service.yml

    UserIpAddress:
        class: AppBundle\Controller\UserIpAddressController
        arguments: 
        container: "@service_container"  
    
    UserIpAddressController.php

    <?php
    namespace ProductBundle\Controller\Tests\Controller;
    use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
    class CategoryControllerTest extends WebTestCase {
    
         protected function setUp() {
            static::$kernel = static::createKernel();
            static::$kernel->boot();
            $this->container = static::$kernel->getContainer();
            $this->em = static::$kernel->getContainer()->get('doctrine')->getManager();
        }
    
        public function testCategory() {
            $ip_address = $_SERVER['REMOTE_ADDR'];
            $client = static::createClient(
              array(), array('HTTP_HOST' => static::$kernel->getContainer()->getParameter('test_http_host')
            ));
    
            $crawler = $client->request('POST', '/category/new');
            $client->enableProfiler();
    
            $this->assertEquals('ProductBundle\Controller\CategoryController::addAction', $client->getRequest()->attributes->get('_controller'));
            $form = $crawler->selectButton('new_category')->form();
            $form['category[name]'] = "Electronics";
            $form['category[id]']   = "For US";
            $form['category[ip]']   = $ip_address;
            $client->submit($form);
    
            $this->assertTrue($client->getResponse()->isRedirect('/category/new')); // check if redirecting properly
            $client->followRedirect();
            $this->assertEquals(1, $crawler->filter('html:contains("Category Created Successfully.")')->count());
        }
    }
    
    class UserIpAddressController
    {
      public function get()
      {
        return $_SERVER['REMOTE_ADDR'];
      }
    }
    
    $UserIpAddress = $this->getMockBuilder('UserIpAddress')
        ->disableOriginalConstructor()
        ->getMock();
    
    $UserIpAddress->expects($this->once())
      ->method('get')
      ->willReturn('192.161.1.1'); // Set ip address whatever you want to use
    
    创建“UserIpAddress”服务的模拟。它将覆盖现有的服务。使用“UserIpAddress”服务获取项目中的ip地址

    CategoryControllerTest.php

    <?php
    namespace ProductBundle\Controller\Tests\Controller;
    use Symfony\Bundle\FrameworkBundle\Test\WebTestCase;
    class CategoryControllerTest extends WebTestCase {
    
         protected function setUp() {
            static::$kernel = static::createKernel();
            static::$kernel->boot();
            $this->container = static::$kernel->getContainer();
            $this->em = static::$kernel->getContainer()->get('doctrine')->getManager();
        }
    
        public function testCategory() {
            $ip_address = $_SERVER['REMOTE_ADDR'];
            $client = static::createClient(
              array(), array('HTTP_HOST' => static::$kernel->getContainer()->getParameter('test_http_host')
            ));
    
            $crawler = $client->request('POST', '/category/new');
            $client->enableProfiler();
    
            $this->assertEquals('ProductBundle\Controller\CategoryController::addAction', $client->getRequest()->attributes->get('_controller'));
            $form = $crawler->selectButton('new_category')->form();
            $form['category[name]'] = "Electronics";
            $form['category[id]']   = "For US";
            $form['category[ip]']   = $ip_address;
            $client->submit($form);
    
            $this->assertTrue($client->getResponse()->isRedirect('/category/new')); // check if redirecting properly
            $client->followRedirect();
            $this->assertEquals(1, $crawler->filter('html:contains("Category Created Successfully.")')->count());
        }
    }
    
    class UserIpAddressController
    {
      public function get()
      {
        return $_SERVER['REMOTE_ADDR'];
      }
    }
    
    $UserIpAddress = $this->getMockBuilder('UserIpAddress')
        ->disableOriginalConstructor()
        ->getMock();
    
    $UserIpAddress->expects($this->once())
      ->method('get')
      ->willReturn('192.161.1.1'); // Set ip address whatever you want to use
    

    现在,使用
    $UserIpAddress->get()获取ip地址

    您可以创建另一个将返回服务器变量的类,然后对其进行模拟

    或者您可以直接在测试用例中设置/取消设置服务器变量。 使用PHPUnit 6.2.2执行此操作:

     /**
     * Return true if the user agent matches a robot agent
     */
    public function testShouldReturnTrueIfRobot()
    {
        $_SERVER['HTTP_USER_AGENT'] = 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)';
    
        $this->configMock->method('getRobotUserAgents')
            ->willReturn('bot|crawl|slurp|spider|mediapartner');
    
        $test = $this->robotTest->isBot();
    
        static::assertTrue($test);
    }
    
    /**
     * Test return false if no user agent
     */
    public function testShouldReturnFalseIfNoAgentUser()
    {
        unset($_SERVER['HTTP_USER_AGENT']);
    
        $test = $this->robotTest->isBot();
    
        static::assertFalse($test);
    }
    
    若试验方法为:

     /**
     * Detect if current user agent matches a robot user agent
     *
     * @return bool
     */
    public function isBot(): bool
    {
        if (empty($_SERVER['HTTP_USER_AGENT'])) {
            return false;
        }
    
        $userAgents = $this->config->getRobotUserAgents();
        $pattern = '/' . $userAgents . '/i';
    
        return \preg_match($pattern, $_SERVER['HTTP_USER_AGENT']);
    }
    

    如果希望使应用程序更易于测试,则不应直接访问
    $\u服务器
    或其他超全局程序。为它们创建容器,然后在测试时模拟它们。即使将行移动到行下方,也不能使用
    REMOTE\u ADDR
    $crawler=$client->request('POST','/category/new')。真的吗?无论如何,那么你真的应该使用选项2,不管怎样,它都是更好的选择。