logo
podcast Podcast
get help Get Unstuck

Why we assert specific validation error messages

Are you testing what you think you are?

Joel Clermont
Joel Clermont
2024-08-19

In a previous tip, I shared our approach to testing validation logic, including how we name the validation tests. Today I want to focus on the specific assertions we make when testing validation logic.

Laravel provides a nice testing helper to assert that a specific field has a validation error:

// inside our test
$response->assertSessionHasErrors([
    'first_name',
    'last_name',
    'email',
]);

This lets me assert that all three of these fields failed validation logic. This is a good start, but it's not quite enough.

Why? Well fields have more than one validation rule attached to them. Continuing our example, the first_name field would have rules for string, required, and max:255. This is a pretty basic example, but it illustrates the point.

With our assertion above, we don't actually know which of these rules failed, just that any one of them did.

How can we make this a stronger test? We can assert the specific error message:

// inside our test
$response->assertSessionHasErrors([
    'first_name' => 'The first name field is required.',
    'last_name' => 'The last name field is required.',
    'email' => 'The email field is required.',
]);

Now I have confidence that all three of these fields specifically failed the required validation rule. This is important to me, especially as the rules get more complicated than our admittedly basic example here.

I've heard some objections to this approach, mostly around the idea that the error messages are subject to change.

It's true, this test is a bit brittle to changes in how Laravel words the error message. And yes, they do change from time to time.

But honestly, it's not a big deal. A few quick "find and replace" commands later, and all the tests are passing again.

If Laravel provided a better way of doing this, for example letting me assert directly which rule failed like Livewire does, I'd switch to that immediately. But until then, this approach gives me a lot more confidence for very little extra effort.

Here to help,

Joel

P.S. I know what you're thinking: this guy sure does think about validation a lot. It's true. Aaron and I even wrote a whole book on Laravel validation rules.

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.