【问题标题】:Laravel Unit Testing - add cookie to request?Laravel 单元测试 - 将 cookie 添加到请求中?
【发布时间】:2020-11-23 23:54:13
【问题描述】:

我想用 json POST 发送一个 cookie:

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

publications 路由有一些中间件:

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

    //cookie validation

    return $next($request);
}

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

怎么了?

真实的(浏览器内)请求没有这样的问题。

【问题讨论】:

    标签: phpunit laravel-5.7


    【解决方案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 响应。

    【讨论】:

      【解决方案2】:

      这应该适用于最新版本(Laravel 6):

      要么:

      $this->disableCookieEncryption();
      

      或:

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

      【讨论】:

      • 感谢您的回答!我一直在尝试找到解决我们的 cookie 加密问题的方法。不幸的是,这不在官方文档中?
      • 如何在 post 请求中做到这一点
      【解决方案3】:

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

      很遗憾,您在单元测试中使用 $request->call()$request->get()$request->post() 发送的所有 cookie 通常都是未加密的,官方文档中没有任何内容告诉您它们需要加密。

      如果您不想每次都调用$request->disableCookieEncryption(),作为永久解决方案,您可以简单地重新定义App\Http\Middleware\EncryptCookies.php 中的isDisabled() 方法以在单元测试期间忽略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);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 2017-05-29
        • 2016-03-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多