phpunit icon indicating copy to clipboard operation
phpunit copied to clipboard

Unexpected failure on assertJson; expected value contains actual value prepended to intended expected value

Open Synchro opened this issue 2 years ago • 1 comments

Q A
PHPUnit version 10.2.1
PHP version 8.2.6
Installation Method Composer

Description

  1. I have a PHPUnit test that contains this:
assertJson(['batch' => null])
  1. 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,
  1. If I then "Click to see difference" (a PHPStorm feature), it shows me this:

image

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.

Synchro avatar Jun 09 '23 08:06 Synchro

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.

sebastianbergmann avatar Jun 09 '23 10:06 sebastianbergmann

@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.

theseer avatar Sep 16 '23 10:09 theseer

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.

Synchro avatar Sep 17 '23 18:09 Synchro