Symfony+API Platform中PHPUnit断言JSON浮点值失败问题排查
问题分析与解决方案
这是Symfony序列化组件的默认行为导致的,并非API Platform或你的代码bug。JSON格式本身没有严格区分整数和浮点数类型,当浮点数的值是整数(比如25.0)时,Symfony的NumberNormalizer会自动将其序列化为整数形式(25),而不是保留浮点格式。
解决方法有两种,按需选择:
1. 强制序列化时保留浮点格式
在实体的cost属性上添加Symfony Serializer的Type注解,明确指定该字段序列化为浮点类型:
use Symfony\Component\Serializer\Annotation\Serializer; #[ApiResource()] class MyEntity { // ... #[ORM\Column(nullable: true)] #[Serializer\Type('float')] private ?float $cost = null; // ... }
添加这个注解后,无论cost的值是25.0还是其他浮点数,API都会返回带小数点的浮点格式,测试的assertJsonContains就能匹配成功。
2. 修改测试逻辑,兼容数值匹配
如果不想修改实体的序列化规则,可以调整测试断言,改用assertEquals比较数值(而非严格匹配数组类型):
public function testGetSingleMyEntity(): void { // ... $response = $client->request('GET', '/api/my_entity/'.$myentity->getId()); $responseData = $response->toArray(); // 比较数值,忽略JSON序列化带来的类型差异 $this->assertEquals($myentity->getCost(), $responseData['cost'], 'Cost value does not match'); }
assertEquals会忽略整数和浮点数的类型差异,只要数值相等就会通过断言,适合不需要严格保证返回格式的场景。
为什么强制转换没用?
你尝试用(float)或floatval()转换值无效,是因为$myentity->getCost()本身已经是float(25.0)类型,但序列化时Symfony的处理逻辑会把整数值的浮点数自动转成整数,所以API返回的JSON里是25,而assertJsonContains是严格匹配数组的键值对类型,因此导致断言失败。
内容的提问来源于stack exchange,提问作者hthomas
相关产品推荐
相关产品推荐

