Unexpected failure on assertJson; expected value contains actual value prepended to intended expected value
| Q | A |
|---|---|
| PHPUnit version | 10.2.1 |
| PHP version | 8.2.6 |
| Installation Method | Composer |
Description
- I have a PHPUnit test that contains this:
assertJson(['batch' => null])
- This test fails, even though you can see that the actual value does indeed contain
'batch' => null:
Unable to find JSON:
[{
"batch": null
}]
within response JSON:
[{
"data": [
{
"type": "products",
"id": "abc123",
"attributes": {
"serial": "abc123",
"status": "Packed",
"batch": null,
- If I then "Click to see difference" (a PHPStorm feature), it shows me this:
There is only one difference (which is the expected JSON shape I'm looking for), but you can see it has been appended to the entire "actual" content, and so it will never match (because the actual will always match itself perfectly, and anything else is excess with nothing to match against). The left hand side of that diff should only contain:
array (
'batch' => NULL
)
It's as if I was doing this (which isn't actually possible):
assertEquals($actual . $expected, $actual)
If I set $expected to [], the test passes!
I can match any single element of my target successfully by using assertJsonFragment, but that is not nearly as flexible as assertJson. What's more, I have this kind of test working perfectly well in other tests in the same app, so it's not a general problem.
I'm unsure where this problem lies - the test should not be failing, but the PHPUnit output shows the correct JSON value for $expected, but when PHPStorm shows the PHP array equivalent of the JSON, it's wrong, and I think that is produced by PHPUnit. I can't think of any way that I could make PHPUnit do this on purpose, so it feels like a bug.
Thank you for your report.
Please provide a minimal, self-contained, reproducing test case that shows the problem you are reporting.
Without such a minimal, self-contained, reproducing test case I will not be able to investigate this issue.
@Synchro We're trying to understand your issue - and use case -, but fail:
Already the inital assertJson(['batch' => null]) cannot work: assertJson expects a string input and only asserts that it is a valid json string by trying to parse it.
I can match any single element of my target successfully by using assertJsonFragment, but that is not nearly as flexible as assertJson. What's more, I have this kind of test working perfectly well in other tests in the same app, so it's not a general problem.
As stated above, assertJson doesn't do what this paragraph implies. It does not look at the actual values in any form. It merely ensures the provided string contains valid json.
So it looks like assertJson is being used wrong.
I see what happened here. I wasn't aware that Laravel replaces some of PHPUnit's methods with methods of the same name – I thought they were just passed through, and that this was an issue with assertJSON in PHPUnit, when it's actually in the completely different assertJSON in Laravel... Apologies for the confusion.