Laravel单元测试-向请求添加cookie?

时间:2019-01-06 17:48:36

标签: phpunit laravel-5.7

我想发送带有JSON POST的cookie:

public function testAccessCookie()
{
    $response = $this->json('POST', route('publications'))->withCookie(Cookie::create('test'));
    //some asserts
}

发布路线具有一些中间件:

public function handle($request, Closure $next)
{
    Log::debug('cookie', [$request->cookies]);

    //cookie validation

    return $next($request);
}

但是在运行testAccessCookie()时,日志中有[null]。没有附加Cookie。

怎么了?

真正的(浏览器中)请求没有这种问题。

3 个答案:

答案 0 :(得分:1)

您可以向测试中的通话添加cookie:

$cookies = ['test' => 'value'];

$response = $this->call('POST', route('publications'), [], $cookies);

请参见https://laravel.com/api/5.4/Illuminate/Foundation/Testing/Concerns/MakesHttpRequests.html#method_call

但是,您将遇到Cookie加密问题。您可以使用以下方法在测试过程中暂时禁用Cookie:

use Illuminate\Cookie\Middleware\EncryptCookies;

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

    return $this;
}

在测试开始时添加$this->disableCookiesEncryption('test');

您可能需要添加标头以指定json响应。

答案 1 :(得分:1)

这应该在最新版本(Laravel 6)中起作用:

要么:

$this->disableCookieEncryption();

或:

$cookies = ['test' => encrypt('value', false)];

$response = $this->call('POST', route('publications'), [], $cookies);

答案 2 :(得分:0)

从Laravel 5.2开始,您将获得\App\Http\Middleware\EncryptCookies::class中间件组中默认定义的web中间件,它将所有未加密的cookie设置为null。

不幸的是,您在单元测试中使用$request->call()$request->get()$request->post()发送的所有cookie通常都是未加密的,并且官方文档中没有任何内容表明您需要对其进行加密。

如果您不想每次都调用$request->disableCookieEncryption(),那么作为永久解决方案,您只需在isDisabled()中重新定义App\Http\Middleware\EncryptCookies.php方法即可在单元测试期间忽略cookie加密。

这是我为Laravel 6.x进行的实现,它也应该在较早的版本上工作。

<?php

namespace App\Http\Middleware;

use Illuminate\Cookie\Middleware\EncryptCookies as Middleware;

class EncryptCookies extends Middleware
{
    /**
     * The names of the cookies that should not be encrypted.
     *
     * @var array
     */
    protected $except = [
        //
    ];

    public function isDisabled($name)
    {
        if (app()->runningUnitTests()) {
            return true;    // Disable cookies encryption/decryption during unit testing
        }

        return parent::isDisabled($name);
    }
}