logo
podcast Podcast
get help Get Unstuck

Understanding how Laravel view assertions work internally

No one likes a passing test when the actual logic is wrong. Here's how to make sure your view assertions are actually testing what you think they are.

Joel Clermont
Joel Clermont
2023-09-15

We previously discussed how Laravel's assertViewHas test helper behaves when trying to assert a value is null. Today, we'll talk about another issue that might catch you off guard if you don't know how the assertion works internally.

Let's say you're trying to test for a boolean value, or a specific numeric value. You might try something like this:

$response->assertViewHas('status', false);

$response->assertViewHas('recordCount', 1);

This seems pretty straightforward, but it may not work quite as you expect:

$response->assertViewHas('status', false); // passes when status is `null` or `0`

$response->assertViewHas('recordCount', 1); // passes when recordCount is `true`

What is happening here? Under the hood, assertViewHas uses PHPUnit's assertEquals assertion, which does a loose comparison of the expected and actual values. If your controller is passing a mixed type, this can cause your test to pass, when you might be expecting it to fail.

What is the solution? My recommendation is to avoid the use of mixed types where possible. For example, if status is always a boolean, there's no possibility for type coercion to confuse the loose comparison. If recordCount is always an integer, you avoid the same issue.

If you absolutely can't avoid a mixed type, you can use a closure to do a strict comparison and avoid the ambiguity.

$response->assertViewHas('status', fn ($value) => $value === false);

$response->assertViewHas('recordCount', fn ($value) => $value === 1);

Here to help,

Joel

P.S. You think this tip is good? You should try our free book of even more Laravel tips to make your application a little bit better.

Toss a coin in the jar if you found this helpful.
Want a tip like this in your inbox every weekday? Sign up below 👇🏼
email
No spam. Only real-world advice you can use.