我有一个名为Info
的JSON对象,它们只有字符串&看起来像这样:
{
"prop1": "value1",
"prop2": "value1",
"timestamp": "2018-02-28T05:30:10.100Z",
"prop4": "value4",
"prop_N": "I have a total of 10 properties."
}
我想将它们与预期的JSON对象进行比较。
为此,我将预期的和实际的JSON转换为Java对象/ POJO。我期望的JSON可以在4个属性中的任何一个中具有空值。如果任何预期的JSON字段为null,那么我希望我的代码不比较这些字段。如果它们不为空,则使用String.equals()
进行比较,但有一个例外:对于始终为UTC的timestamp
,我们必须忽略秒和&毫秒。
比较结果将用于JUnit断言方法,以检查收到的实际JSON是否与预期的JSON匹配。
我已经实现了如下所示的代码。但是,有两个问题:
有人可以建议如何解决这些问题吗?
public boolean matchesInfo(Info givenInfo) throws Exception {
if (this.getProp1() != null) {
boolean prop1Matching = this.getProp1().equals(givenInfo.getProp1());
if (prop1Matching == false){return false;}
}
// More if blocks like this. Very long and ugly.
// For timestamp comparison, call a custom function to strip seconds, milliseconds.
}
答案 0 :(得分:1)
不是将JSON反序列化为对象以便于比较,而是可以使用JsonUnit来促进测试用例中有意义的“JSON比较”。
下面有一些例子可以解决你问题中的观点...显示有意义的回答(即命名不匹配的字段/值),忽略空/缺少字段。还有更多详细信息in the docs,包括使用自定义匹配器来处理此要求:“对于始终为UTC的时间戳,我们必须忽略秒和毫秒。”。
@Test
public void canAssertJsonEquality() {
String expected = "{\n" +
" \"prop1\": \"value1\",\n" +
" \"prop2\": \"value1\"\n" +
"}";
String actual = "{\n" +
" \"prop1\": \"value1\",\n" +
" \"prop2\": \"value1\"\n" +
"}";
JsonAssert.assertJsonEquals(expected, actual);
}
@Test
public void canAssertJsonEqualityRegardlessOfPropertyOrder() {
String expected = "{\n" +
" \"prop1\": \"value1\",\n" +
" \"prop2\": \"value1\"\n" +
"}";
String actual = "{\n" +
" \"prop2\": \"value1\",\n" +
" \"prop1\": \"value1\"\n" +
"}";
JsonAssert.assertJsonEquals(expected, actual);
}
@Test
public void canIgnoreFieldsWhichAreInActualButNotInExpected() {
String expected = "{\n" +
" \"prop2\": \"value1\"\n" +
"}";
String actual = "{\n" +
" \"prop1\": \"value1\",\n" +
" \"prop2\": \"value1\"\n" +
"}";
JsonAssert.assertJsonEquals(expected, actual, JsonAssert.when(Option.IGNORING_EXTRA_FIELDS));
}
// fails with ...
// Different keys found in node "", expected: <[prop1, prop2]> but was: <[prop2]>. Missing: "prop1"
@Test
public void willFailIfActualIsMissingAProperty() {
String expected = "{\n" +
" \"prop1\": \"value1\",\n" +
" \"prop2\": \"value1\"\n" +
"}";
String actual = "{\n" +
" \"prop2\": \"value1\"\n" +
"}";
JsonAssert.assertJsonEquals(expected, actual);
}
// fails with ...
// Different value found in node "prop1", expected: <"value1"> but was: <"value2">.
@Test
public void willFailIfActualHasAnIncorrectValue() {
String expected = "{\n" +
" \"prop1\": \"value1\",\n" +
" \"prop2\": \"value1\"\n" +
"}";
String actual = "{\n" +
" \"prop1\": \"value2\",\n" +
" \"prop2\": \"value1\"\n" +
"}";
JsonAssert.assertJsonEquals(expected, actual);
}
答案 1 :(得分:0)
有几种方法可以使用 ModelAssert - https://github.com/webcompere/model-assert 解决此问题。
首先,我们可以断言我们感兴趣的字段:
assertJson(actual)
.at("/prop1").isText("value1")
.at("/prop2").isText("value2");
或者,我们可以使用 isEqualTo
方法,将某些路径标记为忽略
assertJson(actual)
.where()
.at("/prop2").isIgnored()
.at("/prop3").isIgnored()
.isEqualTo(expected);
assertJson
将接受 String
、JsonNode
甚至是 Map/POJO,它在比较之前将其序列化为 JSON。同样,isEqualTo
也允许这样做。
ModelAssert 还支持 YML,并且可以将其断言表示为 Hamcrest 匹配器。它解释了事情失败时的差异。