Java MockMvc 测试和匹配 Json 字符串

Posted

技术标签:

【中文标题】Java MockMvc 测试和匹配 Json 字符串【英文标题】:Java MockMvc Test and Match Json String 【发布时间】:2021-12-22 13:33:09 【问题描述】:

我想匹配get-request的输出,并匹配手动提供的json字符串,基本上是从整个输出中复制一个json字符串并测试。尝试了很多方法但它没有发生,我无法从数据库中删除所有行以匹配一个字符串,所以,我只想匹配一个 json 字符串 - 如下所示


        "instanceName": "",
        "read": 1,
        "swProduct": "Area 1",
        "swProductModule": "Regular 1"
    ,

这是我的测试代码---


@SpringBootTest(classes = TestApplication.class)
@ActiveProfiles("dev")
@AutoConfigureMockMvc

public class SwStatusCheckTest 

    @Autowired
    private MockMvc mvc;

    @IfProfileValue(name = "spring.profiles.active", values =  "dev" )
    @Test
    @DisplayName("GET Method /SwCheckStatus check success")
    public void testStatusSuccess() throws Exception 

        MvcResult result =  mvc.perform(get("/status/SwCheckStatus"))
                .andDo(print())
                .andExpect(status().isOk())
                .andReturn();
                //.andExpect(content().json("\"services\":[\"OutboundMessageService\"]", true));

        String actualJson = result.getResponse().getContentAsString();
        String expectedJson = "[\"instanceName\":\"Instance C\", \"read\" : 1, \"swProduct\" : \"Area 3\", \"swProductModule\" : \"Spring Boot 3\"]";


        assertThat(expectedJson).isIn(actualJson);




整个 Postman json 结果的输出如下所示 ---

[
    
        "instanceName": "",
        "read": 1,
        "swProduct": "Area 1",
        "swProductModule": "Regular 1"
    ,
    
        "instanceName": "",
        "read": 1,
        "swProduct": "Area 1",
        "swProductModule": "Regular 2"
    ,
    
        "instanceName": "",
        "read": 1,
        "swProduct": "Area 1",
        "swProductModule": "Spring Boot 1"
    ,
    
        "instanceName": "",
        "read": 1,
        "swProduct": "Area 1",
        "swProductModule": "Spring Boot 2"
    ,

Intellij 说 -- 它的期望和字符串匹配......但测试失败 -- 检查附件 --- [在此处输入图片说明][1]

非常感谢您对执行测试的任何见解帮助。 [1]:https://i.stack.imgur.com/FE2dT.jpg

【问题讨论】:

【参考方案1】:

isIn 不是比较字符串,而是数组。

您可以将JSONMap 进行比较,与jackson-databind 和Google Guava:


import static org.assertj.core.api.Assertions.assertThat;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Maps;
import java.util.List;
import java.util.Map;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.annotation.IfProfileValue;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;

@SpringBootTest(classes = TestApplication.class)
@ActiveProfiles("dev")
@AutoConfigureMockMvc

public class SwStatusCheckTest 

    @Autowired
    private MockMvc mvc;

    @IfProfileValue(name = "spring.profiles.active", values =  "dev" )
    @Test
    @DisplayName("GET Method /SwCheckStatus check success")
    public void testStatusSuccess() throws Exception 

        MvcResult result = mvc.perform(get("/status/SwCheckStatus"))
            .andDo(print())
            .andExpect(status().isOk())
            .andReturn();
        //.andExpect(content().json("\"services\":[\"OutboundMessageService\"]", true));

        ObjectMapper mapper = new ObjectMapper();

        List<? extends Map<String, Object>> actualJson = mapper.readValue(result.getResponse().getContentAsString(),
            List.class);

        Map<String, Object> expected = Map.of("instanceName", "", "read", 1, "swProduct", "Area 1", "swProductModule",
            "Regular 1");

        boolean contains = false;
        for (Map<String, Object> a : actualJson) 
            boolean res = Maps.difference(a, expected).areEqual();
            if (res) 
                contains = true;
                break;
            
        
        assertThat(contains).isTrue();
    

【讨论】:

【参考方案2】:

如果我正确阅读了您的问题以及您发布的图片,则问题可能是预期/实际字符串或测试中定义的条件(断言)。 “实际”字符串值是一个包含多个元素的数组,“预期”是一个只有一个元素的数组。由于只有一个元素的数组不包含在多个元素的数组中,所以它不起作用。

如果代码发生更改,使得您要查找的“预期”值被写为 JUST 对象(不包括其封闭数组)

 ... your object here ... 

那么预期的“isIn”实际断言应该可以工作。

【讨论】:

我只需要匹配一个字符串...来自 result.getResponse().getContentAsString(); 的输出

以上是关于Java MockMvc 测试和匹配 Json 字符串的主要内容,如果未能解决你的问题,请参考以下文章

是否有任何适当的匹配器来解析和比较来自 MockMvc 的 Json 响应中的 LocalDateTime 字段

Spring MVC 测试,MockMVC:方便地将对象与 JSON 进行转换

MockMvc 测试 POST 请求

java Spring Test MockMvc测试实例

java 使用@MockMvc对@Controller进行单元测试

MockMVC的使用