【问题标题】:How to use server variables in PHPUnit Test cases?如何在 PHPUnit 测试用例中使用服务器变量?
【发布时间】:2017-05-26 03:00:04
【问题描述】:

我正在使用 PHPUnit 测试用例测试模块。一切正常,但当我使用$_SERVER['REMOTE_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());
    }
}

错误

有 1 个错误:

1) ProductBundle\Tests\Controller\CategoryControllerTest::testCategory 未定义索引:REMOTE_ADDR

我已尝试将其添加到 setUp() 函数中,但效果不佳。

【问题讨论】:

  • 如果您想让您的应用程序更具可测试性,您不应该直接访问$_SERVER 或其他超全局变量。为它们创建容器,然后在测试时模拟它们。

标签: php symfony phpunit


【解决方案1】:

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

要解决这个问题:

  1. 将线移到下方:

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

就像 cmets 中提到的 @apokryfos 一样,在测试用例中访问超全局变量被认为是不好的做法。所以选项 2 可能是您最好的选择。

【讨论】:

  • 即使将行移至$crawler = $client-&gt;request('POST', '/category/new');的下一行,您也不能使用REMOTE_ADDR
  • 真的吗?无论如何,那你真的应该使用选项 2,无论如何这是更好的选择。
【解决方案2】:

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

在这里,将控制器和服务创建为 UserIpAddressget() 将返回用户的 IP 地址。

service.yml

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

UserIpAddressController.php

class UserIpAddressController
{
  public function get()
  {
    return $_SERVER['REMOTE_ADDR'];
  }
}

创建“UserIpAddress”服务的模拟。它将覆盖现有服务。使用“UserIpAddress”服务获取项目中的 IP 地址。

CategoryControllerTest.php

$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-&gt;get();获取IP地址

【讨论】:

    【解决方案3】:

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

    或者您可以直接在您的测试用例中设置/取消设置服务器变量。 用 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']);
    }
    

    【讨论】:

    • 确保在测试后取消设置任何更改,因为更改会在其他更改中持续存在,可能会给您带来麻烦。
    猜你喜欢
    • 1970-01-01
    • 2012-03-04
    • 1970-01-01
    • 1970-01-01
    • 2010-12-28
    • 2022-07-22
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多