logo
podcast Podcast
get help Get Unstuck

An unhelpful error message with enums and assertJson

You might be scratching your head

Joel Clermont
Joel Clermont
2025-02-03

Here's an interesting scenario I bumped into recently.

Let's say you want to test an API response and your value includes a backed enum:

// app/Enums/Urgency.php
enum Urgency: string {
    case LOW = 'low';
    case MEDIUM = 'medium';
    case HIGH = 'high';
}

// tests/Feature/ExampleTest.php
$response->assertJson([
    'data' => [
        'urgency' => Urgency::LOW,
    ],
])

This test will fail, because the backed enum doesn't match the string value in the JSON response. It's an easy fix, just add ->value to the enum and your test passes. No big deal!

But here's where it gets interesting. Look closely at the test failure error message:

Unable to find JSON: 

[{
    "data": {
        "urgency": "low"
    }
}]

within response JSON:

[{
    "data": {
        "urgency": "low"
    }
}]

The two values match! And this example is extremely simple, so the weirdness is easier to spot, but now imagine it within a response with dozens of keys and values.

What is going on?

Inside Laravel's assertJson test method, it defers the assertion to PHPUnit::assertArraySubset. As expected the PHPUnit method sees the BackedEnum object and the string value as different, so the test fails as it should.

But when Laravel calls that PHPUnit assertion, it also passes in the error message to show if the assertion fails. And to make the error message more nicely-formatted, it formats both the expected and actual values with json_encode with pretty printing.

When you json_encode a BackedEnum object, it will return the string value of the enum, not the enum object itself.

So the test is failing, but the error message looks like it should have passed.

Here to help,

Joel

P.S. Despite the occasional confusing error message, testing is one of the single best things you can do to keep your app easy to maintain. Would you like some help introducing testing to your app?

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.