Laravel 中间件共享变量 View 在编写 HTTP 测试时不起作用

标签 laravel phpunit middleware laravel-testing

我们有以下中间件。我们知道中间件是有效的,因为在浏览器中测试应用程序是有效的。遗憾的是,在编写 HTTP 测试用例时,blade 说中间件定义的变量不存在。

<?php

namespace App\Http\Middleware;

use App\Repository\UserContract;
use Closure;
use Illuminate\Contracts\View\Factory as ViewFactory;
use Illuminate\Support\Facades\View;

class Authenticate
{
    private $userRepository;
    private $view;

    public function __construct(UserContract $userRepository, ViewFactory $view)
    {
        $this->userRepository = $userRepository;
        $this->view = $view;
    }

    public function handle($request, Closure $next)
    {
        $userId = null;
        $username = null;
        if ($request->hasCookie('auth')) {
            $secret = $request->cookie('auth');
            $userId = $this->userRepository->getUserIdBySecret($secret);
            $username = $this->userRepository->getUsername($userId);
        }
        $this->view->share('username', $username);
        $request['_user_id'] = $userId;
        $request['_username'] = $username;
        return $next($request);
    }
}

我们进行 PHPUnit 测试如下:

    /**
     * @test
     */
    public function it_shows_logged_in_username()
    {
        $app = $this->createApplication();
        $encrypter = $app->get(Encrypter::class);
        $userRepository = $app->make(UserContract::class);
        $userRepository->addUser('jane', 'secret');

        $secret = $encrypter->encrypt('secret', false);
        $response = $this->call('GET', '/', [], ['auth' => $secret], [], [], null);
        $response->assertSeeText('jane');
    }

错误

ErrorException {#980                                                                                                                                           
  #message: "Undefined variable: username"                                                                                                                     
  #code: 0                                                                                                                                                     
  #file: "./storage/framework/views/db4b9232a3b0957f912084f26d9041e8a510bd6c.php"
  #line: 3                                                                     
  #severity: E_NOTICE                                                          
  trace: {                                                                     
    ./storage/framework/views/db4b9232a3b0957f912084f26d9041e8a510bd6c.php:3 {
      › <?php dump($comments); ?>                                              
      › <?php dump($username); ?>  

有什么建议吗?

编辑

我必须补充一点,使用View外观并调用它的share方法使其可以工作,但我遇到了同样的问题,错误 变量应该由 \Illuminate\View\Middleware\ShareErrorsFromSession 股票 laravel 中间件设置。

其他说明,我的中间件称为 Authenticate 但它与 Laravel 的基于密码的普通身份验证无关。

这里是UserContract:

<?php
declare(strict_types=1);


namespace App\Repository;


use App\Repository\Exception\UserAlreadyRegisteredException;

interface UserContract
{
    public function isRegistered(string $username): bool;

    public function getUserID(string $username): int;

    public function getUserIdBySecret(string $secret): int;

    /**
     * @param int $userId
     *
     * @return string
     * @throws
     */
    public function getUsername(int $userId): string;

    /**
     * @param int $userId
     *
     * @return string
     * @throws AuthSecretNotSetException
     */
    public function getUserAuthSecret(int $userId): string;

    public function getNextId(): int;

    /**
     * @param string $username
     * @param string $authSecret
     *
     * @return int
     * @throws UserAlreadyRegisteredException
     */
    public function addUser(string $username, string $authSecret): int;

    public function fetchUpdatedBetween(?\DateTimeInterface $start, ?\DateTimeInterface $end): array;

    public function markAsSynced(int $userId): void;

    public function isSynced(int $userId): bool;

    public function delete(int $userId): void;

    public function markAsDeleted(int $userId): void;

    public function fetchDeletedIds(): array;

    public function removeDeletedFlag(int $userId): void;

    public function fetchStalledIds(\DateTimeInterface $dateTime): array;

    public function purge(int $userId): void;

    /**
     * @param UserFetcherContract $fetcher the closure would be passed userId and it should return data or null
     */
    public function setFallbackFetcher(UserFetcherContract $fetcher): void;
}

最佳答案

要正确测试登录,您应该提交一个发布请求,因此请更改:

$response = $this->call('GET', '/', [], ['auth' => $secret], [], [], null);

$response = $this->call('POST', '/', [], ['auth' => $secret], [], [], null);




或者,如果您只想测试 View 而不是登录表单本身,则可以使用 actingAs 方法...

创建时在变量中捕获用户:

$user = $userRepository->addUser('jane', 'secret');

使用 actingAs 方法以登录的 $user 身份测试 View :

$this->actingAs($user)->get('/')->assertSeeText('jane');;

关于Laravel 中间件共享变量 View 在编写 HTTP 测试时不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57847185/

相关文章:

Laravel 过滤日期之间的数据

php - 使用 Laravel 中的验证器检查两个表中两列的唯一性

php - Symfony2 phpunit 测试认证

laravel - Controller Laravel 5.4 中的多个中间件

laravel - 尝试catch在Laravel中间件中无法正常工作吗?

php - 在 Laravel 5.7 中插入/更新一百万行的最快方法

mysql - Laravel eloquent - 如何在自定义关系中使用 DB raw

phpunit - phpunit 测试完成后如何运行脚本

php - 在 Laravel 中使用 Mockery/phpUnit 时出错

python - django 中间件导致的重定向循环