使用MockMvc的Hamcrest:检查该键是否存在但值可能为null

我正在使用MockMvc进行一些测试,我想validationJSON响应的结构。 具体来说,我想确保属性的键存在,并且该值是某个类型或null。

{ "keyToNull": null, # This may be null, or a String "keyToString": "some value" } 

以下对我有用,但我想知道是否有办法将每组两个期望合并为一行,因为我有很多要检查的属性:

 import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; import static org.hamcrest.Matchers.*; .andExpect(jsonPath("$").value(hasKey("keyToNull"))) .andExpect(jsonPath("$.keyToNull").value( anyOf(any(String.class), nullValue(String.class)))) .andExpect(jsonPath("$").value(hasKey("keyToString"))) .andExpect(jsonPath("$.keyToString").value( anyOf(any(String.class), nullValue(String.class)))) 

hasKey()是必需的,因为另一个断言本身通过,因为MockMvc的实现映射中不存在的键映射为null:

 .andExpect(jsonPath("$.notAKey").value( anyOf(any(String.class), nullValue(String.class)))) // ok 

jsonPath().exists()也不起作用,因为在内部它将值与null进行比较。

我考虑过这样一个单独的方法:

 private static  void assertNullableAttr(ResultActions res, String jsonPath, Class type) throws Exception { int split = jsonPath.lastIndexOf('.'); String prefix = jsonPath.substring(0, split), key = jsonPath.substring(split+1); res.andExpect(jsonPath(prefix).value(hasKey(key))) .andExpect(jsonPath(jsonPath).value(anyOf(any(type), nullValue(type)))); } 

但后来它迫使我以不自然的方式分割我的代码:

 ResultActions res = mockMvc.perform(get("/api")) // these attributes must not be null .andExpect(jsonPath("$.someInfo").value(hasSize(2))) .andExpect(jsonPath("$.someInfo[0].info1").value(any(String.class))) .andExpect(jsonPath("$.someInfo[0].info2").value(any(String.class))) .andExpect(jsonPath("$.addlInfo").value(hasSize(2))) .andExpect(jsonPath("$.addlInfo[0].info1").value(any(String.class))) .andExpect(jsonPath("$.addlInfo[0].info2").value(any(String.class))); // these attributes may be null assertNullableAttr(res, "$.someInfo[0].info3", String.class); assertNullableAttr(res, "$.someInfo[0].info4", String.class); assertNullableAttr(res, "$.addlInfo[0].info3", String.class); assertNullableAttr(res, "$.addlInfo[0].info4", String.class); 

是否有任何聪明的Hamcrest Matcher我可以应用于每个属性的单个json路径?

您可以添加以下静态匹配器工厂:

 public static  Matcher> hasNullKey(K key) { return new IsMapContaining(equalTo(key), anyOf(nullValue(), anyString()); } 

然后,您可以像这样使用它:

 // will succeed, because keyToNull exists and null .andExpect(jsonPath("$").value(hasNullKey("keyToNull"))) // will succeed, bacause keyToString exists and not null .andExpect(jsonPath("$").value(hasNullKey("keyToString"))) // will fail, because notAKey doesn't exists .andExpect(jsonPath("$").value(hasNullKey("notAKey"))) 

您可以使用以下现有测试类执行此操作:

 .andExpect(jsonPath("$..myExpectedNullKey[0]").value(IsNull.nullValue())); 

一定要导入org.hamcrest.core.IsNull

我在这个博客中找到了这个解决方案:

 .andExpect(jsonPath( "$.keyToNull").doesNotExist()); 

这个对我有用。