首页 > 解决方案 > 使用 AssertJ 在同一个对象上断言多个 JsonNode 路径?

问题描述

我使用的是assertj-core 3.9.1,但我也用我可用的最新版本3.16.1对此进行了测试。

我正在尝试使一些 assertj 断言更清晰一些。我们经常在非平凡的层次结构级别为各种对象断言多个子属性。我一直在使用“提取”从对象中提取简单的属性,但我现在要做的事情有点复杂,而且它不起作用。我所看到的似乎是 assertj 中的一个错误,但我不确定它为什么会这样做。

我从这样的事情开始:

assertThat(expression).at("/content/liability").asText()).isEqualTo("CRU");
assertThat(expression).at("/content/enterpriseType").asText()).isEqualTo("GBS");

我想做这样的事情:

assertThat(expression)
    .extracting(jn -> jn.at("/content/liability").asText(),
                jn -> jn.at("/content/enterpriseType").asText())
    .containsExactly("CRU", "GBS");

这失败了,基本上说我希望“[]”(一个空列表)等于[“CRU”,“GBS”]。

我仍然有上面的原始断言,使用相同的表达式,所以我知道数据在那里。该表达式返回如下结构:

{
  "content": {
    ...
    "enterpriseType": "GBS",
    ...
    "liability": "CRU",
    ...
  }
}

所以,然后我尝试将断言更改为:

assertThat(expression))
    .extracting(jn -> textAtPath(jn, "/content/liability"),
                jn -> textAtPath(jn, "/content/enterpriseType"))
    .containsExactly(tuple("CRU", "GBS"));

和:

private String textAtPath(JsonNode node, String path) {
    return node.at(path).asText();
}

然后我在“textAtPath”中使用断点运行测试。我在那里看到的东西看起来很正常,直到我仔细观察。当我查看“节点”的值时,我看到一些看起来很像我上面展示的结构,但不完全是:

{
  ...
  "enterpriseType": "GBS",
  ...
  "liability": "CRU",
  ...
}

由于某种原因,传递给“extracting()”的 lambda 的值是原始结构的 CHILD 节点。

我尝试更改测试,因此两个路径字符串是“/liability”和“/enterpriseType”。测试通过了。我不会就这样离开它,因为这没有任何意义。

标签: javajsonjacksonassertj

解决方案


我相信这在https://github.com/joel-costigliola/assertj-core/issues/1954中有讨论。

这里的微妙之处在于,如果 expression 是可迭代的,assertThat(expression) 将提供可迭代的断言并将extracting应用于可迭代的元素。

另一方面,如果assertThat(expression)已返回对象断言,extracting将应用于表达式。

我还强烈建议将JsonUnit用于 JSON 断言。


推荐阅读