如何比较 kotlinx 中的实际序列化结果和预期序列化结果?

How to compare actual and expected serialization result in kotlinx?

注意:我是 Kotlin/JUnit 生态系统的新手,所以如果问题缺少一些基本内容,请耐心等待。

我正在研究基于 JSON 的文件格式。在 unit/integration 测试中,我想检查序列化生成的 JSON 树是否与某些参考 JSON 树完全相同。特别是我想确保序列化正确处理隐式或显式空值等细微之处。

我以普通 .json 文件的形式添加了预期的 JSON 作为测试资源,这样我现在可以加载预期的 JSON 的字符串内容。我的问题是我的测试用例需要一些 deep/complex JSON 树,如果比较失败,我找不到 获得有意义的测试输出的好方法。例如,考虑 JSON 树深处某处只有一个值错误的情况。在 Rust 中,我正在使用 rust-pretty-assertions 来解决这些问题:

我已经尝试过这些方法:

  1. 比较基于JsonElement。我基本上使用:

     val actualContent: String = ... # from serialization
     val expectedContent: String = ... # from test fixture
     val actual = Json.parseToJsonElement(actualContent)
     val expected = Json.parseToJsonElement(expectedContent)
     Assertions.assertEquals(actual, expected)
    

    不幸的是,如果比较失败,测试输出只包含一行 org.opentest4j.AssertionFailedError: expected: <{ ... long unformatted JSON ...}>,这使得很难发现断言失败的实际原因。当然,这种行为是有道理的,因为如果 JsonElement.equals returns false,JUnit 只能打印它。

  2. 直接字符串比较:这当然不是完美的,因为JSON-树即使字符串表示不同也可以是相同的。然而,我希望对它们进行漂亮的序列化将允许我在 JUnit 中使用某种字符串差异功能。到目前为止,我使用的是 JUnit 的普通 Assertions.assertEquals(actual, expected),不幸的是它只打印两个字符串,说它们不相等,没有提示它们不同的地方。

kotlinx 或 JUnit 中是否有可以生成易于解释的测试失败输出的功能?

以防万一:我使用的是 JUnit 5,但我愿意接受其他选择。

我建议尝试 JsonUnit。它将允许您为 json 编写断言,并在失败时显示良好的消息。使用 AssertJ 集成的示例:

assertThatJson(actual).isEqualTo(expectedJson)

...可能会在与您的示例类似的示例中产生以下输出:

Comparing expected:
{"lorem":"Hello, Wrold!","ipsum":42,"dolor":{"value":"hey ho!"}}
------------
with actual:
{"lorem":"Hello, World!","ipsum":42,"dolor":{"value":"hey"}}

Different value found in node "dolor.value", expected: <"hey ho!"> but was: <"hey">.
Comparison Failure: 
Expected :hey ho!
Actual   :hey

Different value found in node "lorem", expected: <"Hello, Wrold!"> but was: <"Hello, World!">.
Comparison Failure: 
Expected :Hello, Wrold!
Actual   :Hello, World!

它将为您的项目添加另一个依赖项,但它仅用于测试范围,非常值得...