6

I am testing modules using PHPUnit Test cases. All the things working fine but when i use $_SERVER['REMOTE_ADDR'] it gives fatal error and stops execution.

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());
    }
}

Error

There was 1 error:

1) ProductBundle\Tests\Controller\CategoryControllerTest::testCategory Undefined index: REMOTE_ADDR

I have tried to add it in setUp() function but it's not working as well.

1
  • 1
    You shouldn't directly access $_SERVER or other superglobals if you want to make your application more testable. Create containers for them and then mock them when testing. Commented Jan 11, 2017 at 10:55

3 Answers 3

1

Technically, you haven't sent a request to your application yet, so there is no remote address to refer to. That in fact is what your error is telling us too.

To work around this:

  1. move the line to be below:

    // Won't work, see comment below    
    $crawler = $client->request('POST', '/category/new');
    
  2. Or you could make up an IP address and test with that. Since you're only using the IP to save a model, that will work just as well.

Like @apokryfos mentioned in the comments, it's considered bad practice to access superglobals in test cases. So option 2 is probably your best choice here.

Sign up to request clarification or add additional context in comments.

2 Comments

You can not use REMOTE_ADDR even after moving line to below line $crawler = $client->request('POST', '/category/new');.
Really? Anyway, then you should really use option 2, which is the better choice no matter what.
1

You can either create another class that will return the server var then mock it.

Or you can set/unset the server var directly into your test case. Did it with 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);
}

Where tested method is :

 /**
 * 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']);
}

1 Comment

Make sure to unset any changes after the test, as the changes will persist in other changes and may give you troubles.
0

Create service which returns ip address and mock the service in test case.

Here, create controller and service as UserIpAddress. get() will return ip address of user.

service.yml

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

UserIpAddressController.php

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

Create mock of "UserIpAddress" service. It will override existing service. Use 'UserIpAddress' service to get ip address in your project.

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

Now, get ip address using $UserIpAddress->get();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.