Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JSON assertions should treat objects as unordered #4674

Closed
Firehed opened this issue May 19, 2021 · 0 comments
Closed

JSON assertions should treat objects as unordered #4674

Firehed opened this issue May 19, 2021 · 0 comments
Labels
feature/assertion Issues related to assertions and expectations type/bug Something is broken

Comments

@Firehed
Copy link
Contributor

Firehed commented May 19, 2021

Q A
PHPUnit version 9.5.4
PHP version 9.0.1
Installation Method Composer

Summary

According to the JSON spec outlined at json.org, an object (dictionaries) "is an unordered set of name/value pairs". PHPUnit's JSON comparsion assertions (assertJsonStringEqualsJsonString and friends) appear to enforce an ordered set.

The internals suggest this is supposed to be handled already. I tried adding SORT_STRING as a flag to ksort here and it seemed to fix things, but I hardly did exhaustive testing.

Somewhat related to #4584, but more in the sense that it's impossible to maintain a native PHP array that 1:1 matches certain JSON due to numeric key conversion. Getting that all correct is tragically difficult.

Current behavior

good compare
Failed asserting that '{"a":{},"d":1,"b":[],"e":-1,"0":null,"c":"1","f":[1,2],"h":{"2":"2","1":"1","0":"0"},"g":[2,1]}' matches JSON string "{
    "0": null,
    "a": {},
    "b": [],
    "c": "1",
    "d": 1,
    "e": -1,
    "f": [1,2],
    "g": [2,1],
    "h": {"0":"0","1":"1","2":"2"}
}".
--- Expected
+++ Actual
@@ @@
 {
-    "0": null,
     "a": {},
     "b": [],
-    "c": "1",
     "d": 1,
     "e": -1,
+    "0": null,
+    "c": "1",
     "f": [
         1,
         2

How to reproduce

    public function testJson(): void
    {
        $expected = <<<'JSON'
        {
            "0": null,
            "a": {},
            "b": [],
            "c": "1",
            "d": 1,
            "e": -1,
            "f": [1,2],
            "g": [2,1],
            "h": {"0":"0","1":"1","2":"2"}
        }
        JSON;

        $this->assertJsonStringEqualsJsonString(
            $expected,
            '{"a":{},"d":1,"b":[],"e":-1,"0":null,"c":"1","f":[1,2],"h":{"2":"2","1":"1","0":"0"},"g":[2,1]}',
            'good compare',
        );
        try {
            $this->assertJsonStringEqualsJsonString(
                $expected,
                '{"a":{},"d":1,"b":[],"e":-1,"0":null,"c":"1","f":[2,1],"h":{"2":"2","1":"1","0":"0"},"g":[2,1]}',
                'bad!',
            );
            $this->fail('should fail: f is transposed');
        } catch (\Throwable $e) {}
        try {
            $this->assertJsonStringEqualsJsonString(
                $expected,
                '{"a":{},"d":1,"b":[],"e":-1,"0":null,"c":"1","f":[1,2],"h":[0,1,2],"g":[2,1]}',
                'bad!',
            );
            $this->fail('should fail: h changed from obj to array (intvals)');
        } catch (\Throwable $e) {}
        //#4584?
        try {
            $this->assertJsonStringEqualsJsonString(
                $expected,
                '{"a":{},"d":1,"b":[],"e":-1,"0":null,"c":"1","f":[1,2],"h":["0","1","2"],"g":[2,1]}',
                'bad!',
            );
            $this->fail('should fail: h changed from obj to array (strings)');
        } catch (\Throwable $e) {}
    }

Expected behavior

Above test case passes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature/assertion Issues related to assertions and expectations type/bug Something is broken
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants