core
core copied to clipboard
ApiTestCase: assertJsonContains throws ArraySubset class not found error
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.
Got the same here. Any suggestions?
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 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
Are you using simple-phpunit
? I'm using this assertion on several projects without issues.
@soyuka I am using the symfony/phpunit-bridge, yes
@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
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 that's exactly our question 😅
Code seems right, but something does not work ☹️
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?
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).
could you try my fix in src/Bridge/Symfony/Bundle/Test/Constraint/ArraySubset.php
?
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
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.
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');
}
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.
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.