ASSERTJ:如何使jsonnode比较句柄intnode和longnode一样?
我有一个jsonnode
,该是由map< string,object>
的构建的:
Map<String, Object> actual = Map.of("test", 3L);
JsonNode actualNode = mapper.valueToTree(actual);
我想将此节点与预期的文件进行比较,我会加载这样的文件
String expected = "{\"test\": 3}";
JsonNode expectedNode = mapper.readTree(expected);
:我打印这两个节点,我发现它们完全相同:
>> System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(expectedNode));
>> System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(actualNode));
{
"test": 3
}
但是,当我使用assert-j
比较两个节点时,我会收到以下错误:
Assertions.assertThat(actualNode).isEqualTo(expectedNode);
java.lang.AssertionError:
Expecting:
<"{"test":3} (ObjectNode@7ef2d7a6)">
to be equal to:
<"{"test":3} (ObjectNode@5dcbb60)">
but was not.
如果我调试.isequalto。
的断言,我看到失败发生是因为:
- 实际节点中的
3
是longnode
(我理解,因为原始映射包含a <代码> 3L ) 3
在预期节点中是intnode
,
因此当测试等式时,intnode
不是即使是longnode
的实例,因此断言失败了。
但是,我真的无法控制MAP
在实际节点背后的构建背后。在这种情况下,我该怎么做才能使断言起作用?
完全可重现的示例:
Map<String, Object> actual = Map.of("test", 3L);
String expected = "{\"test\": 3}";
ObjectMapper mapper = new ObjectMapper();
JsonNode expectedNode = mapper.readTree(expected);
JsonNode actualNode = mapper.valueToTree(actual);
Assertions.assertThat(actualNode).isEqualTo(expectedNode);
PS我目前已经通过序列化和划分节点来修复它:
JsonNode newActualNode = mapper.readTree(mapper.writeValueAsString(actualNode));
...但是我正在寻找更清洁的东西。
I have a JsonNode
which is built out of a Map<String, Object>
:
Map<String, Object> actual = Map.of("test", 3L);
JsonNode actualNode = mapper.valueToTree(actual);
I would like to compare such node against an expected file, that I load as such:
String expected = "{\"test\": 3}";
JsonNode expectedNode = mapper.readTree(expected);
When I print these two nodes, I see that they are exactly the same:
>> System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(expectedNode));
>> System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(actualNode));
{
"test": 3
}
However, when I compare the two nodes using assert-j
, I get the following error:
Assertions.assertThat(actualNode).isEqualTo(expectedNode);
java.lang.AssertionError:
Expecting:
<"{"test":3} (ObjectNode@7ef2d7a6)">
to be equal to:
<"{"test":3} (ObjectNode@5dcbb60)">
but was not.
If I debug the .isEqualTo
of the assertion, I see that the failure happens because:
- The
3
in the actual node is aLongNode
(which I understand since the original map contains a3L
) - The
3
in the expected node though is anIntNode
So when the equality is tested, the IntNode
is not even an instanceof LongNode
and so the assertion fails.
However, I really don't control how the Map
behind the actual node is built. What can I do to make the assertion work in this case?
Fully reproducible example:
Map<String, Object> actual = Map.of("test", 3L);
String expected = "{\"test\": 3}";
ObjectMapper mapper = new ObjectMapper();
JsonNode expectedNode = mapper.readTree(expected);
JsonNode actualNode = mapper.valueToTree(actual);
Assertions.assertThat(actualNode).isEqualTo(expectedNode);
P.s. I have currently fixed it by serializing and deserializing the node:
JsonNode newActualNode = mapper.readTree(mapper.writeValueAsString(actualNode));
... but I was looking for something cleaner.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
原因是因为杰克逊(Jackson)默认为
int
,它可以适合未型值(即最多32位)。因此,assertj
(甚至木星的断言)已经正确失败了断言,因为实际和预期的确实是两种不同的类型。此行为可以通过DeserializationFeature.USE_LONG_FOR_INTS
功能控制。该物业的Java文档的最后一句话说。当创建
ObjectMapper
杰克逊将不必要地创建值的值时,您可以简单地启用它。
The reason is because the jackson defaults to
int
when it can fit in the untyped value (i.e up to 32 bit). So theassertj
(even the jupiter assertions) has correctly failed the assertion, because actual and expected are indeed two different types. This behaviour can be controlled by theDeserializationFeature.USE_LONG_FOR_INTS
feature. The last sentence of the java doc of that property says this;You can simply enable it when you create the
ObjectMapper
The downside is jackson will create values in larger long type unnecessarily.
正如您发现的那样,ASSERTJ在报告节点并不等于一个有一个长的孩子,而另一个则具有int。
您写道:
证明了他们的
toString
方法产生相同的结果。这与它们完全相同。如果您要寻找的是验证节点的
toString
,则:As you have discovered, AssertJ is behaving correctly in reporting that the nodes are not equal as one has a long child and the other has an int.
You wrote:
Printing the nodes using
toString
proves that theirtoString
methods produce the same result. That's not the same as them being exactly the same.If what you are looking for is to validate the
toString
of the node then:jsonunit with assertj样式可能是最好的选择:
但是,我期望 assertj递归比较也可以正常工作:
但事实并非如此。
我创建了#2672 跟踪这种潜在的改进。
JsonUnit with AssertJ style is probably the best option:
However, I would have expected the AssertJ recursive comparison to work as well:
but this is not the case.
I created #2672 to track this potential improvement.