core icon indicating copy to clipboard operation
core copied to clipboard

ApiTestCase: assertJsonContains throws ArraySubset class not found error

Open geoff-maddock opened this issue 4 years ago • 14 comments

API Platform version(s) affected: 2.5.9

Description
This issue started after upgrading API Platform core from 2.5.7 to 2.5.9

When making an assertion such as:

        $this->assertJsonContains([
            'content' => '127.0.0.1',
        ]);

The ArraySubset class is not being found:

20) App\Tests\Functional\ZoneTest::testPutMasterIp
Error: Class 'ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubset' not found

/srv/api/vendor/api-platform/core/src/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php:98
/srv/api/vendor/api-platform/core/src/Bridge/Symfony/Bundle/Test/ApiTestAssertionsTrait.php:57
/srv/api/tests/Functional/ZoneTest.php:126

Looking at ArraySubset, it was changed from a class to an alias which should match to: ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubsetV9 or ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubsetLegacy

Which both appear to be in the project.

How to reproduce
Make a call to $this->assertJsonContains in a class that extends ApiTestCase

Possible Solution
Unknown.

Additional Context
Symfony 4.4. In phpunit.xml.dist we have

        <server name="SYMFONY_PHPUNIT_VERSION" value="8.3" />

I tried 8.4 and got the same error. 8.5 and I ran into more issues.

geoff-maddock avatar Jan 15 '21 20:01 geoff-maddock

Got the same here. Any suggestions?

massimilianobraglia avatar Jan 19 '21 15:01 massimilianobraglia

My work around was re-writing the tests I was using to use assertJsonEquals.
Made my tests a bit harder to read/longer, but it was doable.

geoff-maddock avatar Jan 19 '21 16:01 geoff-maddock

@geoff-maddock thank you. I thought something like your workaround but unfortunately I got tons of test using this constraint.

Probably is better to copy that class (after removing the alias) and use directly the copy. Some help would be appreciated

massimilianobraglia avatar Jan 19 '21 16:01 massimilianobraglia

Are you using simple-phpunit? I'm using this assertion on several projects without issues.

soyuka avatar Jan 22 '21 09:01 soyuka

@soyuka I am using the symfony/phpunit-bridge, yes

massimilianobraglia avatar Jan 22 '21 11:01 massimilianobraglia

@geoff-maddock I just tried another workaround and it seems to work well: in your phpunit bootstrap file just add the following:

use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubset;
use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubsetV9;

// [...]

if (!\class_exists(ArraySubset::class)) {
    class_alias(ArraySubsetV9::class, ArraySubset::class);
}

In this way the ArraySubsetV9 is explicitly loaded once and aliased as ArraySubset

massimilianobraglia avatar Jan 22 '21 14:01 massimilianobraglia

Weird as we do this already in https://github.com/api-platform/core/blob/main/src/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php or are we missing something?

soyuka avatar Feb 02 '21 14:02 soyuka

@soyuka that's exactly our question 😅

Code seems right, but something does not work ☹️

massimilianobraglia avatar Feb 02 '21 14:02 massimilianobraglia

I have an idea can you try changing the code at src/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php by:

<?php

/*
 * This file is part of the API Platform project.
 *
 * (c) Kévin Dunglas <[email protected]>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

declare(strict_types=1);

namespace ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint;

use PHPUnit\Runner\Version;
use PHPUnit\SebastianBergmann\Comparator\ComparisonFailure;
use SebastianBergmann\Comparator\ComparisonFailure as LegacyComparisonFailure;
use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubsetV9;
use ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubsetLegacy;

if (!class_exists(ComparisonFailure::class)) {
    class_alias(LegacyComparisonFailure::class, 'PHPUnit\SebastianBergmann\Comparator\ComparisonFailure');
}

final class ArraySubset extends Constraint {}

// Aliases as string to avoid loading the class
if (\PHP_VERSION_ID >= 80000 || (float) Version::series() >= 9) {
    class_alias(ArraySubsetV9::class, ArraySubset::class);
} else {
    class_alias(ArraySubsetLegacy::class, ArraySubset::class);
}

To see if it changes something?

soyuka avatar Feb 02 '21 15:02 soyuka

Same happens to me. I'm using the last 2.6.2 version of api platform. Used @massimilianobraglia tip of doing that special alias in the tests bootstrap.php and it works for me.

I'm using Symfony 5.2 with phpunit 8 set in the phpunit.xml (which will download the last phpunit 8.x).

monteiro avatar Feb 19 '21 07:02 monteiro

could you try my fix in src/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php ?

soyuka avatar Feb 19 '21 09:02 soyuka

Sorry @soyuka, I did not manage to try your solution. Instead we found that in dev env we used a wrong composer flag when installing the dependencies:

https://getcomposer.org/doc/articles/autoloader-optimization.md#optimization-level-2-a-authoritative-class-maps

Using this only in prod environment fixes the issue for me

massimilianobraglia avatar Mar 04 '21 15:03 massimilianobraglia

I also have the same problem. As mentioned by @massimilianobraglia, It seems to be caused by authoritative class maps in the test environment of the CI. When using this flag locally the tests also fail. The change suggested by @soyuka (thanks 🙏) in https://github.com/api-platform/core/issues/3962#issuecomment-771700251 unfortunately does not solve it.

yakobe avatar Mar 19 '21 16:03 yakobe

still broken due to composer dump-autoload --classmap-authoritative

worked around by putting this in my test cases:

if(!class_exists('ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubset', false)){
    class_alias('ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubsetV9', 'ApiPlatform\Core\Bridge\Symfony\Bundle\Test\Constraint\ArraySubset');
}

bendavies avatar May 19 '22 13:05 bendavies

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Nov 04 '22 21:11 stale[bot]

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

stale[bot] avatar Jan 04 '23 01:01 stale[bot]