简体   繁体   English

Laravel 测试通过了 auth 中间件但通过数据提供者的 Auth::user() 失败

[英]Laravel test passes auth middleware but fails Auth::user() with data providers

I am testing my Laravel application with the integrated PHPUnit configuration and I have problems with the authentication of a user inside a test.我正在使用集成的 PHPUnit 配置测试我的 Laravel 应用程序,并且在测试中对用户进行身份验证时遇到问题。

I have this test (shortened)我有这个测试(缩短)

public function testShowEditForm($user, $expectedStatus, $expectedLocation, $expectedSee, $expectedDontSee) {
    if ($user !== null)
        $this->actingAs($user);

    // $this->assertAuthenticatedAs($user); -> This is true!

    $response = $this->get("/objects/edit/");

    $response->assertStatus($expectedStatus);

    // [...]
}

with this data provider:使用此数据提供者:

public function showEditFormProvider() {
    return [
        'allowedUser' => [
            UserGenerator::getControllingUser(),
            200,
            null,
            ["something"],
            []
        ]
    ];
}

The UserGenerator::getControllingUser() just triggers the User Factory, adds some rights and returns the user object. UserGenerator::getControllingUser()只是触发用户工厂,添加一些权限并返回用户 object。

The tested method (also shortened):测试方法(也缩短):

public function edit($object_id = null) {
    $user = User::find(Auth::user()->id); // Auth::user() returns null
    // [...]
}

The route for this method is encapsuled inside the "middleware" => "auth" part in the routes/web.php此方法的路由封装在 routes/web.php 中的"middleware" => "auth"部分中

Problem: The data provider is correctly called, it passes the middleware but the Auth::user() call in the edit() method returns null - so the authentication seems to have failed anyway regardless the passing through the middleware?问题:数据提供者被正确调用,它通过了中间件,但是edit()方法中的Auth::user()调用返回 null - 所以无论通过中间件,身份验证似乎都失败了?

  • If I replace the parameter $user in the testShowEditForm directly with UserGenerator::getControllingUser(), it works (but this isn't a good workaround because I have a lot of test cases and so I need the data providers).如果我直接用 UserGenerator::getControllingUser() 替换 testShowEditForm 中的参数 $user,它可以工作(但这不是一个好的解决方法,因为我有很多测试用例,所以我需要数据提供者)。
  • So I worked around by calling the data provider by $this->showEditFormProvider() in the first line of the test method testShowEditForm() - but it gets called twice (what is the correct behaviour according to this 1 ).所以我通过在测试方法 testShowEditForm() 的第一行中通过 $this->showEditFormProvider() 调用数据提供程序来解决 - 但它被调用了两次(根据 this 1的正确行为是什么)。 But this is also not the ideal workaround, because if I create an object in the provider to test, it gets created also twice and so the assertions fail.但这也不是理想的解决方法,因为如果我在提供程序中创建一个 object 进行测试,它也会被创建两次,因此断言失败。

Is there anything I'm doing wrong?有什么我做错了吗? I already searched a lot for this topic and the actingAs() / be() methods in the testing method seem to be the best practice for mocking a logged in user.我已经为此主题进行了很多搜索,并且测试方法中的actingAs() / be()方法似乎是登录用户 mocking 的最佳实践。

1 "All data providers are executed before both the call to the setUpBeforeClass static method and the first call to the setUp method." 1 “所有数据提供程序都在调用 setUpBeforeClass static 方法和第一次调用 setUp 方法之前执行。” https://phpunit.de/manual/3.7/en/writing-tests-for-phpunit.html https://phpunit.de/manual/3.7/en/writing-tests-for-phpunit.html

In Laravel 5.8 it worked using在 Laravel 5.8 中,它使用

$user = User::find(Auth::id());

instead of代替

$user = User::find(Auth::user()->id); // Auth::user() returns null

inside the Controller. Controller 内部。 I have no idea why, but maybe it will help some searching dev in the future.我不知道为什么,但也许它会在未来帮助一些搜索开发人员。 Funnily enough, since Laravel 6 (currently my app is on 6.10.0), no more problems, even with the "old" implementation.有趣的是,自从 Laravel 6(目前我的应用程序在 6.10.0 上)以来,即使使用“旧”实现,也没有更多问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM