Hamcrest with MockMvc:检查密钥是否存在,但值可能为空

问题描述 投票:9回答:4

我正在使用MockMvc做一些测试,我想验证JSON响应的结构。具体来说,我想确保属性键存在,并且值是某种类型或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))))

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

hasKey()

[.andExpect(jsonPath("$.notAKey").value( anyOf(any(String.class), nullValue(String.class)))) // ok 也不起作用,因为它在内部将值与jsonPath().exists()进行比较。

我已经考虑过制作这样的单独方法:

null

但是这迫使我以不自然的方式拆分代码:

private static <T> void assertNullableAttr(ResultActions res, String jsonPath, Class<T> 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))));
    }

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

java hamcrest jsonpath mockmvc
4个回答
4
投票

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

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);

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

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

18
投票

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

// 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")))

请确保导入org.hamcrest.core.IsNull


9
投票

我在此.andExpect(jsonPath("$..myExpectedNullKey[0]").value(IsNull.nullValue())); 中找到了此解决方案:

blog

它对我有用。


0
投票

这里是我的解决方案:

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

希望这会有所帮助!

© www.soinside.com 2019 - 2024. All rights reserved.