Paupoo's avatar
Level 1

Feature test that fails, while I can't reproduce in the app myself

Hello,

I'm quite a newbie, learning by myself programming and many concepts. I've come to start TDD, unit testing and so on.

I'm hitting one wall for now. I've already started building without knowing about testing :) After reading docs, videos and so on, I've managed to build and run some basics tests, and adapt the tests created by the Breeze package.

Everything works, except this test (original from the package). I suspect that's because I'm using some relations in the view, and somehow I don't understand how to make it right in the test unit, but don't know how to work this out.

The test :

public function test_profile_page_is_displayed(): void
{
    $user = User::factory()->create();

    $response = $this
        ->actingAs($user)
        ->get('/profile');

    $response->assertOk();
}

The error

FAILED Tests\Feature\ProfileTest > profile page is displayed Expected response status code [200] but received 500. Failed asserting that 500 is identical to 200.

then many lines [...]

Attempt to read property "name" on null

at tests/Feature/ProfileTest.php:21 17▕ $response = $this 18▕ ->actingAs($user) 19▕ ->get('/profile'); 20▕ ➜ 21▕ $response->assertOk(); 22▕ } 23▕ 24▕ public function test_profile_information_can_be_updated(): void 25▕ {

Tests: 1 failed, 25 passed (61 assertions) Duration: 3.30s

Here below, one of the 2 blocks in the view that I could isolate. In fact I use, by default to fill 2 inputs, the role and the team relationships (both user "belongsTo" and themselves being "hasMany"). In my app, no problem, no issue, code 200 with everything working fine, but the testing never likes it and get error 500 it seems.

    <div>
        <x-input-label for="team" :value="__('Team')" />
        <x-text-input id="team" name="team" type="text" class="block mt-1 w-14" :value="old('team', $user->team->name)" disabled autofocus />
        <x-input-error class="mt-2" :messages="$errors->get('team')" />
    </div>

When I modify "$user->team->name" or "$user->team->role" with "$user->role_id" and "$user->team_id", it works all tests are passed, but I don't want to see the ID's in my view...

Can someone help solving this ? I assume that "->actingAs($user)" is only passing the user model, without relationships, but if I'm correct I don't know how to solve in the test case. In the view, I aslo tried to change "$user->" with "Auth::user()->", still works, but test unit still fails.

Voilà, I would be grateful at the end when I will understand my issue, thank you in advance !

0 likes
5 replies
MikhArt's avatar

You need to do it either in view like this $user->team?->name or create corresponding relation in test (team for user)

1 like
Paupoo's avatar
Level 1

@MikhArt Wow, first thanks for your very quick answer. All my tests are passed, and no regression in real life testing. What a relief already ! How do I need to understand the "?" in the view next to the name of the related model ? I don't find any explanation in the doc... I guess is a sort of "if it's null, ignore it ?"

How would you recommend me second option ? Because in the test environment I've created a dedicated DB, I'm migrating everything, I'm using a factory to inject the id to relate to the team/role models, the relationship is set in the model... So i was naively expecting that it would be automatic... :) What shall I do there ?

MikhArt's avatar
MikhArt
Best Answer
Level 2

@Paupoo ?-> is so-called nullsafe operator in php. https://wiki.php.net/rfc/nullsafe_operator

Can you show the code of UserFactory?

In test it should be something like:

$user = User::factory()->create();
$team = Team::factory()->create();

$user->team()->associate($team);

$response = $this
        ->actingAs($user)
        ->get('/profile');

Or better incapsulate this logic in UserFactory

1 like
Paupoo's avatar
Level 1

@MikhArt OK the nullsafe operator is something I've met in some other exercises. Very interesting.

A great idea, so I could create a team, store it in a variable and then associate with the laravel method. Still a newbie, but reading your answer helps me understand.

Thank you very much !

1 like

Please or to participate in this conversation.