Skip to content

Commit d40b7fd

Browse files
test(state): add test for Symfony 8.1 BackedEnumNormalizer with null expectedTypes
Simulates the behavior from symfony/serializer PR #62574 where an invalid enum value produces an exception with expectedTypes=null and a user-friendly message listing valid values. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent aa8a16f commit d40b7fd

1 file changed

Lines changed: 42 additions & 0 deletions

File tree

src/State/Tests/Provider/DeserializeProviderTest.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,48 @@ public function testDeserializeUsesExceptionMessageWhenCanUseMessageForUser(): v
246246
}
247247
}
248248

249+
/**
250+
* Simulates Symfony 8.1 BackedEnumNormalizer behavior (symfony/serializer PR #62574):
251+
* when a value has the right type but is not a valid enum case, the exception
252+
* is created with expectedTypes=null and a user-friendly message listing valid values.
253+
*/
254+
#[IgnoreDeprecations]
255+
public function testDeserializeUsesExceptionMessageWhenExpectedTypesIsNull(): void
256+
{
257+
$operation = new Post(deserialize: true, class: \stdClass::class);
258+
$decorated = $this->createStub(ProviderInterface::class);
259+
$decorated->method('provide')->willReturn(null);
260+
261+
$exception = new NotNormalizableValueException(
262+
message: "The data must be one of the following values: 'hearts', 'diamonds', 'clubs', 'spades'",
263+
path: 'suit',
264+
useMessageForUser: true,
265+
);
266+
$partialException = new PartialDenormalizationException('Denormalization failed.', [$exception]);
267+
268+
$serializerContextBuilder = $this->createMock(SerializerContextBuilderInterface::class);
269+
$serializerContextBuilder->method('createFromRequest')->willReturn([]);
270+
$serializer = $this->createMock(SerializerInterface::class);
271+
$serializer->method('deserialize')->willThrowException($partialException);
272+
273+
$provider = new DeserializeProvider($decorated, $serializer, $serializerContextBuilder);
274+
$request = new Request(content: '{"suit":"invalid"}');
275+
$request->headers->set('CONTENT_TYPE', 'application/json');
276+
$request->attributes->set('input_format', 'json');
277+
278+
try {
279+
$provider->provide($operation, [], ['request' => $request]);
280+
$this->fail('Expected ValidationException');
281+
} catch (ValidationException $e) {
282+
$violations = $e->getConstraintViolationList();
283+
$this->assertCount(1, $violations);
284+
$this->assertSame("The data must be one of the following values: 'hearts', 'diamonds', 'clubs', 'spades'", $violations[0]->getMessage());
285+
$this->assertSame("The data must be one of the following values: 'hearts', 'diamonds', 'clubs', 'spades'", $violations[0]->getMessageTemplate());
286+
$this->assertSame('suit', $violations[0]->getPropertyPath());
287+
$this->assertSame((string) Type::INVALID_TYPE_ERROR, $violations[0]->getCode());
288+
}
289+
}
290+
249291
#[IgnoreDeprecations]
250292
public function testDeserializeUsesTypeMessageWhenCannotUseMessageForUser(): void
251293
{

0 commit comments

Comments
 (0)