Thanks to visit codestin.com
Credit goes to github.com

Skip to content

[Serializer] test: discriminator without matching property #50472

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

Closed
wants to merge 1 commit into from

Conversation

soyuka
Copy link
Contributor

@soyuka soyuka commented May 30, 2023

Q A
Branch? 6.2
Bug fix? no
New feature? no
Deprecations? no
License MIT

#50193 breaks a test on API Platform w/ Symfony 6.2.11 where the discriminator has no matching property.

Fixture: https://github.com/api-platform/core/blob/main/tests/Fixtures/TestBundle/Entity/AbstractDummy.php
Feature: https://github.com/api-platform/core/blob/main/features/main/crud_abstract.feature#L108-L132

This adds a failing test case, but I'm unsure whether our test case misuses the discriminator feature (does it require a property matching the discriminator ?) or if the #50193 fix breaks.

ping @HypeMC wdyt can you help me on that?

@soyuka soyuka requested a review from dunglas as a code owner May 30, 2023 12:19
@carsonbot carsonbot added this to the 6.2 milestone May 30, 2023
@soyuka soyuka force-pushed the fix/serializer-abstract branch from ee61a55 to 0efb68f Compare May 30, 2023 12:20
@carsonbot carsonbot changed the title test: discriminator without matching property [Serializer] test: discriminator without matching property May 30, 2023
@HypeMC
Copy link
Contributor

HypeMC commented May 30, 2023

Hi, here's what I was able to figure out: unfortunately your test case doesn't really illustrate the real issue since $loaderMock doesn't return the right data, it should look something like this:

        $loaderMock = new class() implements ClassMetadataFactoryInterface {
            public function getMetadataFor($value): ClassMetadataInterface
            {
                if (ConcreteWithDiscriminator::class === $value) {
                    return new ClassMetadata(ConcreteWithDiscriminator::class);
                }

                throw new InvalidArgumentException();
            }

            public function hasMetadataFor($value): bool
            {
                return ConcreteWithDiscriminator::class === $value;
            }
        };

I know this because I've tested the following cases on a clean Symfony installation:

$serializer->denormalize(['id' => 0, 'instance' => 'test', 'name' => 'test'], ConcreteWithDiscriminator::class, 'any');
$serializer->denormalize(['id' => 0, 'instance' => 'test', 'name' => 'test', 'discr' => 'concrete'], AbstractWithDiscriminator::class, 'any');

$serializer->denormalize(['id' => 0, 'instance' => 'test', 'name' => 'test'], AbstractWithDiscriminator::class, 'any');

Both before and after #50193 the first two cases work, while the third one throws an exception:

  Type property "discr" not found for the abstract object "App\DTO\AbstractWithDiscriminator".

With the API Platform test case things are a little different because the ItemNormalizer adds AbstractNormalizer::OBJECT_TO_POPULATE to the context, so your test case would look like this:

$this->serializer->denormalize(
    ['id' => 0, 'instance' => 'test', 'name' => 'test'],
    AbstractWithDiscriminator::class,
    'any',
    [AbstractNormalizer::OBJECT_TO_POPULATE => $object = new ConcreteWithDiscriminator()],
);

Again, for this case, both before and after #50193 an exception is thrown.

The only reason your test passed before is because the AbstractItemNormalizer overrides the instantiateObject() method, but since getMappedClass() is now called before instantiateObject(), your test breaks.

That being said, I do think this is a bug in Symfony since it would make sense for the last example to pass, at least in my opinion, and as far as I can tell the fix is really simple, so I'll try to open a PR.

@nicolas-grekas
Copy link
Member

Thanks for the report and the test case to illustrate the issue!
Closing in favor of #50480, please have a look there 🙏

nicolas-grekas added a commit that referenced this pull request May 31, 2023
…actNormalizer::OBJECT_TO_POPULATE` (HypeMC)

This PR was merged into the 6.2 branch.

Discussion
----------

[Serializer] Fix discriminator map not working with `AbstractNormalizer::OBJECT_TO_POPULATE`

| Q             | A
| ------------- | ---
| Branch?       | 6.2
| Bug fix?      | yes
| New feature?  | no
| Deprecations? | no
| Tickets       | Fix #50472
| License       | MIT
| Doc PR        | -

Ensures that the mapped class is taken from `AbstractNormalizer::OBJECT_TO_POPULATE` if it's set.

Commits
-------

da82f53 [Serializer] Fix discriminator map not working with `AbstractNormalizer::OBJECT_TO_POPULATE`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants