Laravel Testing - Testing Middleware

Posted by Andy Huggins on June 07, 2018

I was working on an a Laravel Spark app today, went to write a test but needed to verify that only a loggedIn user could access this part of the app. I ran the usual `php artisan make:test ListingTest` which makes a Test class in the Features directory.

The file was automatically opened in Code for me using my Open On Make Package. Easy enough. I wrote the base test method setup and began setting up my test.

Looks something like this:

/** @test */
public function it_loads_create_listing_page_for_users()
{
// $this->withoutExceptionHandling();
$user = factory(\App\User::class)->states('verified')->make();
$this->be($user);
$response = $this->get('listing/create');
$response->assertStatus(200);
}

I ran the test and got back kind of a cryptic error:

I knew from Adam Wathan's Test Driven Laravel course, that there was probably some more useful information but it was being swallowed up by the Exception handling that Laravel automatically does. So I used the `$this->withoutExceptionHandling()` helper method in my test to see if I could get a more helpful error message.

The test now looks like this:

/** @test */
public function it_loads_create_listing_page_for_users()
{
$this->withoutExceptionHandling();
$user = factory(\App\User::class)->states('verified')->make();
$this->be($user);
$response = $this->get('listing/create');
$response->assertStatus(200);
}

The error message did change, but it was not super helpful. Here is what I got now:

I started digging, trying to figure out what was going on. I found that the `shouldHaveSelfVisibility()` was being called in the UserRepository that Spark uses, and I even traced it down as being called in the Spark::scriptVariables() call that basically loads a lot of data into the JS app so that you can do some JS things based on the data loaded.

I traced it down to the `InitialFrontEndState->forUser()` function, and even figured out that for some reason it looked like the Auth class was able to return a user, but for some reason not an ID from `Auth::id()`.

This seemed quite odd to me, "why is there a user but not an id? How is that possible?"

I did some Googling trying to see if someone else had run into this issue before and posted about it...nothing really turned up.

I started thinking about the idea of "how is there a user, but not an id?" I opened up my test code again and read it.

Nothing was making sense, was there a different Auth class for Spark? No. Is there something different with the tests? No. What was going on? Am I the first person to write a test for a Spark App, or probably more likely, the first to find this bug in this version?

But I knew the Auth was working because I could do Auth::user() and get the user, so I `dd(\Auth::user())` one time just to see if anything stood out.

Everything looks pretty normal, but as I read through the Attributes array, I noticed, "wait a minute, there is no id for this user." When you create a user you should have an id, but this one in the test does not...why?

I then jumped over to the Test code again and looked at the first line.

$user = factory(\App\User::class)->states('verified')->make();

The factory looks right, but why no id? Then it dawned on me.

->make();

The make() function just makes an instance of a class, it doesn't save to the db, the db is where the auto-incremented id is attached. I thought, I bet you money if I change that to ->create() it will work because the Spark code that looks for the user calls `Auth::id()` and by using create() the user would now have an ID.

Updated the tetst code to look like this:

/** @test */
public function it_loads_create_listing_page_for_users()
{
// $this->withoutExceptionHandling();
$user = factory(\App\User::class)->states('verified')->create();
$this->be($user);
$response = $this->get('listing/create');
$response->assertStatus(200);
}

Ran the test again and we have green.

Posting this in the hopes that if anyone else Google's any of the mentioned function calls, this might help them out.