You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用MockMvcTester断言JSON对象列表并映射为List<MyDto>

如何使用MockMvcTester对JSON对象列表进行断言?

你希望将接口响应的JSON列表映射为List<CardResponseDto>并进行断言,但当前代码转换后得到的是LinkedHashMap集合,存在未检查警告且断言无法生效(使用Spring Boot 4版本)。

你的测试代码如下:

import com.example.em_card_service.data.dto.response.CardResponseDto;
import com.example.em_card_service.service.CardService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.assertj.MockMvcTester;

import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;

@WebMvcTest(CardController.class)
class CardControllerTest {

    @Autowired
    MockMvcTester mvcTester;
    @MockitoBean
    CardService cardService;

    @Test
    void findAll_givenCardsPresent_returns200_andExpectedDtos() {
        UUID cardId = UUID.randomUUID();
        String number = "**** **** **** 1234";
        CardResponseDto card = CardResponseDto.builder().id(cardId).number(number).build();
        List<CardResponseDto> cards = List.of(card);
        given(cardService.findAll(any())).willReturn(cards);

        assertThat(mvcTester.get().uri("/api/admin/cards").exchange())
                .hasStatusOk()
                .bodyJson().convertTo(List.class)
                .satisfies(c -> {
                    assertThat(c).hasSize(1);
                    // unchecked warning, besides it doesn't work: the list has LinkedHashMap, not my DTO
                    assertThat(c).containsExactlyElementsOf(cards);
                });
    }
}

解决方案

问题根源在于Java的类型擦除:直接使用List.class时,Jackson无法识别列表的泛型元素类型,只能将JSON对象转换为LinkedHashMap。要解决这个问题,需要使用ParameterizedTypeReference来保留泛型类型信息,让Jackson正确转换为List<CardResponseDto>。

修改后的测试代码如下:

import com.example.em_card_service.data.dto.response.CardResponseDto;
import com.example.em_card_service.service.CardService;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.webmvc.test.autoconfigure.WebMvcTest;
import org.springframework.test.context.bean.override.mockito.MockitoBean;
import org.springframework.test.web.servlet.assertj.MockMvcTester;
import org.springframework.core.ParameterizedTypeReference;

import java.util.List;
import java.util.UUID;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.BDDMockito.given;

@WebMvcTest(CardController.class)
class CardControllerTest {

    @Autowired
    MockMvcTester mvcTester;
    @MockitoBean
    CardService cardService;

    @Test
    void findAll_givenCardsPresent_returns200_andExpectedDtos() {
        UUID cardId = UUID.randomUUID();
        String number = "**** **** **** 1234";
        CardResponseDto card = CardResponseDto.builder().id(cardId).number(number).build();
        List<CardResponseDto> cards = List.of(card);
        given(cardService.findAll(any())).willReturn(cards);

        // 使用ParameterizedTypeReference指定泛型列表类型
        ParameterizedTypeReference<List<CardResponseDto>> typeRef = new ParameterizedTypeReference<>() {};

        assertThat(mvcTester.get().uri("/api/admin/cards").exchange())
                .hasStatusOk()
                .bodyJson().convertTo(typeRef)
                .satisfies(responseCards -> {
                    assertThat(responseCards).hasSize(1);
                    // 现在可以直接断言DTO列表,无警告且断言生效
                    assertThat(responseCards).containsExactlyElementsOf(cards);
                });
    }
}

关键说明

  • ParameterizedTypeReference是Spring提供的工具类,用于在运行时保留泛型类型信息,避免类型擦除导致的转换问题。
  • 通过convertTo(typeRef)调用,Jackson会将响应的JSON数组正确反序列化为List<CardResponseDto>,而非LinkedHashMap的列表。
  • 修改后不再有未检查警告,且containsExactlyElementsOf断言可以正常生效,因为列表元素类型与预期一致。

内容的提问来源于stack exchange,提问作者Sergey Zolotarev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.02 02:15:06