Masahiro  Hanawa
Masahiro Hanawa

Reputation: 133

user-agent can't get on phpunit

I'm using laravel 5 and 'jenssegers/agent'. user-agent can get when user access by browser.

But, When I use php-unit, user-agent can't get. Do you know this cause? When I check about http-headers. it looks like don't send this header informations.

According to a survey, When I use

var_dump($request->header('user-agent')); 
var_dump($request->server('HTTP_USER_AGENT')); 
var_dump($_SERVER['HTTP_USER_AGENT']);

on controller and exec phpunit. $request->header('user-agent'), var_dump($request->server('HTTP_USER_AGENT')); can get parameter. but, var_dump($_SERVER['HTTP_USER_AGENT']); doesn't get. I expect to 'jenssegers/agent' use $_SERVER parameters.

    public function testAccessAsiPhone()
{
    $headers = [
        'user-agent' => 'Mozilla/5.0 (iPhone; CPU iPhone OS 11_0 like Mac OS X) AppleWebKit/604.1.38 (KHTML, like Gecko) Version/11.0 Mobile/15A372 Safari/604.1'
    ];
    $this->withServerVariables($this->transformHeadersToServerVars($headers))
            ->visit('/')
            ->see('iPhone')
            ->see('iOS')
            ->see('Safari');
}

Upvotes: 1

Views: 1783

Answers (1)

scrowler
scrowler

Reputation: 24405

I haven't seen the code that you're testing, but perhaps you shouldn't rely on superglobals for your code. Aside, I think you're having trouble because the request object that represents $_SERVER doesn't get updated when you update your $_SERVER value.

In terms of your code you can assume that $_SERVER['HTTP_USER_AGENT'] will return the correct agent, so your code shouldn't be concerned with it.

Instead of this (hypothetical):

public function doSomething()
{
    if ($_SERVER['HTTP_USER_AGENT'] === 'iPhone') {
        return 'apple';
    }
    return 'banana';
}

You can separate it out so you can mock it:

public function doSomething()
{
    if ($this->getUserAgent() === 'iPhone') {
        return 'apple';
    }
    return 'banana';
}

public function getUserAgent()
{
    return $_SERVER['HTTP_USER_AGENT'];
}

And now you can mock the parts of your code that your unit test isn't concerned with:

public function testDoSomething()
{
    $mock = $this->getMockBuilder(YourClass::class)
        ->setMethods(['getUserAgent'])
        ->getMock();

    $mock->expects($this->once())->method('getUserAgent')->willReturn('iPhone');

    $this->assertSame('apple', $mock->doSomething());
}

Hope this helps.

Upvotes: 1

Related Questions