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.
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.
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
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?
- 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).
- 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). 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.
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.
1 "All data providers are executed before both the call to the setUpBeforeClass static method and the first call to the setUp method." https://phpunit.de/manual/3.7/en/writing-tests-for-phpunit.html
Answer
In Laravel 5.8 it worked using
$user = User::find(Auth::id());
instead of
$user = User::find(Auth::user()->id); // Auth::user() returns null
inside the 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.
Related Questions
- → "failed to open stream" error when executing "migrate:make"
- → October CMS Plugin Routes.php not registering
- → OctoberCMS Migrate Table
- → OctoberCMS Rain User plugin not working or redirecting
- → October CMS Custom Mail Layout
- → October CMS - How to correctly route
- → October CMS - Conditionally Load a Different Page
- → Make a Laravel collection into angular array (octobercms)
- → In OctoberCMS how do you find the hint path?
- → How to register middlewares in OctoberCMS plugin?
- → Validating fileupload(image Dimensions) in Backend Octobercms
- → OctoberCMS Fileupload completely destroys my backend
- → How do I call the value from another backed page form and use it on a component in OctoberCms