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

assertEqualsCanonicalizing() produces confusing message when elements cannot be converted to string #4923

Open
kiler129 opened this issue Mar 9, 2022 · 2 comments
Labels
type/bug Something is broken

Comments

@kiler129
Copy link

kiler129 commented Mar 9, 2022

Q A
PHPUnit version 9.5.18
PHP version 8.1.2
Installation Method PHAR

Summary

When assertEqualsCanonicalizing() is utilized the assertion result display will crash when one of the array elements, which is presented in the diff, is not castable to string.

Current behavior

When test is run the testing framework crashes with, at-first confusing, error message:

1) FooTest::testFoo
Object of class stdClass could not be converted to int

How to reproduce

<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;

final class FooTest extends TestCase
{
    public function testFoo(): void
    {
       $data = [
            'one' => 123,
            'two' => new \stdClass(),
        ];

        $copy = $data;
        $copy['one'] = 1234;

        $this->assertEqualsCanonicalizing($data, $copy);
    }
}

Expected behavior

The diff should handle such cases properly and display e.g. object ID, similarly to how e.g. assertSame() does it:

1) FooTest::testFoo
Failed asserting that two arrays are identical.
--- Expected
+++ Actual
@@ @@
 Array &0 (
-    'one' => 123
+    'one' => 1234
     'two' => stdClass Object &000000000000000d0000000000000000 ()
 )
@kiler129 kiler129 added the type/bug Something is broken label Mar 9, 2022
@thomasnordahl-dk
Copy link

I can confirm this bug.

It seems to happen here: https://github.com/sebastianbergmann/comparator/blob/main/src/ArrayComparator.php#L56

It seems to happen when an array contains both objects and scalar values, which would be a common case for serialized objects.

This is a problem in cases where you want to compare a list of objects, but the order doesn't matter.

A potential solution could be to use usort() with a custom sorting function that handles cases like this. I would assume that if it handled objects compared to scalar values with simply saying that a scalar value is lower than an object and then compared other cases as per usual, then the problem would be solved.

A temporary fix in the case I've encountered is to "pre-serialize" the objects in the list before asserting.

@kubawerlos
Copy link
Contributor

@kiler129 @thomasnordahl-dk is it still an issue for you? At PHPUnit 10 (lowest supported, currently) the example from here gives:

There was 1 failure:

1) Test::testFoo
Failed asserting that two arrays are equal.
--- Expected
+++ Actual
@@ @@
 Array (
-    'one' => 123
+    'one' => 1234
     'two' => stdClass Object ()
 )

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

No branches or pull requests

3 participants