Java MockMvc Тестирует и сопоставляет строку Json

#java #spring-boot #junit #mockmvc

Вопрос:

я хочу сопоставить вывод get-запроса и сопоставить с предоставленной вручную строкой 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 предназначен не для сравнения строк, а для массивов.

Вы можете сравнить JSON as Map с 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.MvcResu<

@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:

Если я правильно читаю ваш вопрос, а также изображение, которое вы опубликовали, проблема заключается либо в ожидаемых/фактических строках, либо в условии (утверждении), определенном в тесте. «Фактическое» строковое значение представляет собой массив из нескольких элементов, «ожидаемое» — массив только из одного элемента. Поскольку массив только из одного элемента НЕ содержится в массиве из нескольких элементов, он не будет работать.

Если код изменен таким образом, что «ожидаемое» значение, которое вы ищете, записывается как ПРОСТО объект (без его заключающего массива)

 { ... your object here ... }
 

Тогда ожидаемое фактическое утверждение «isIn» должно сработать.

Комментарии:

1. мне нужно сопоставить только одну строку… исходя из вывода result.GetResponse().getContentAsString();