Framework: [5.2] Cookies sent in test are not present in request.

Created on 26 Jan 2016  路  8Comments  路  Source: laravel/framework

Basically, I'm unable to test if controller accepts cookie no matter what i try.

Here's my test:

public function test_cookie_passed_to_request(){
    $cookie = cookie('name', 'value');
    $this->call('get', 'test', [], [$cookie]);
    $this->assertEquals('value', $this->response->content());
}

And here is the route:

Route::get('test', [
    'middleware' => 'web',
    function (\Illuminate\Http\Request $request) {
        return $request->cookie('name');
    }
]);

Test fails: expected "value", got "".

Discussion on laracasts for reference.

Most helpful comment

Here's the final solution.
The test:

public function test_cookie_passed_to_request()
{
    $this->disableCookiesEncryption('name');
    $cookie = [ 'name' => 'value' ];
    $this->call('get', 'test', [ ], $cookie);
    $this->assertEquals('value', $this->response->content());
}

The route:

Route::get('test', [
    'middleware' => 'web',
    function (\Illuminate\Http\Request $request) {
        return $request->cookie('name');
    }
]);

TestCase function to disable cookie encryption:

    /**
     * @param array|string $cookies
     * @return $this
     */
protected function disableCookiesEncryption($cookies)
{
    $this->app->resolving(EncryptCookies::class,
        function ($object) use ($cookies) {
            $object->disableFor($cookies);
        });

    return $this;
}

All 8 comments

This is not a bug, but instead the cookie should be passed as an array of values, not as a Symfony\Component\HttpFoundation\Cookie instance. Test should be changed to read:

    public function test_cookie_passed_to_request(){
        $cookie = ['name' => Crypt::encrypt('value')];

        $this->call('GET', 'test', [], $cookie);

        $this->assertEquals('value', $this->response->content());
    }

Top tip. Avoid calling global functions inside tests. ;)

@GrahamCampbell

And I did some more digging:

$cookie1 = ['name1' => Crypt::encrypt('value1')];
$cookie2 = ['name2' => Crypt::encrypt('value2')];
$this->call('get', 'test', [], [$cookie1, $cookie2]);
$this->assertEquals('value1', $this->response->content());

That test fails.
And here is method definition from src:

public function call($method, $uri, $parameters = [], $cookies = []...

It says $cookies and not cookie. Yet it accepts only one cookie and that one should be weirdly parsed.

as per my answer on the Laracasts thread, the cookies need to be set like:

    public function test_cookies_passed_to_request()
    {
        $cookies = [
            'name1' => Crypt::encrypt('value1'),
            'name2' => Crypt::encrypt('value2')
        ];
        $this->call('get', 'test', [], $cookies);
        $this->assertEquals('value1', $this->response->content());
    }

Here's the final solution.
The test:

public function test_cookie_passed_to_request()
{
    $this->disableCookiesEncryption('name');
    $cookie = [ 'name' => 'value' ];
    $this->call('get', 'test', [ ], $cookie);
    $this->assertEquals('value', $this->response->content());
}

The route:

Route::get('test', [
    'middleware' => 'web',
    function (\Illuminate\Http\Request $request) {
        return $request->cookie('name');
    }
]);

TestCase function to disable cookie encryption:

    /**
     * @param array|string $cookies
     * @return $this
     */
protected function disableCookiesEncryption($cookies)
{
    $this->app->resolving(EncryptCookies::class,
        function ($object) use ($cookies) {
            $object->disableFor($cookies);
        });

    return $this;
}

Working in 5.4

Thanks @asvae! Works perfectly in 5.6

Can we do it without creating routes?

Was this page helpful?
0 / 5 - 0 ratings