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

Spring Boot MockMvc测试报错:No mapping for GET /content及JSON断言失败

问题:Spring Boot控制器MockMvc测试报错:No mapping for GET /content及JSON路径断言失败

错误日志

10:24:51.840 [main] INFO org.springframework.test.web.servlet.TestDispatcherServlet -- Initializing Servlet ''
10:24:51.842 [main] INFO org.springframework.test.web.servlet.TestDispatcherServlet -- Completed initialization in 1 ms
10:24:51.865 [main] WARN org.springframework.web.servlet.PageNotFound -- No mapping for GET /content

java.lang.AssertionError: No value at JSON path "$.duration"

ContentController代码

package com.example.sixth.controller;

import com.example.sixth.entity.Content;
import com.example.sixth.service.ContentService;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Optional;

@RestController
public class ContentController {

    private final ContentService contentService;

    public ContentController(ContentService contentService) {
        this.contentService = contentService;
    }

    @GetMapping("/content")
    public List<Content> show(){
        return contentService.showAll();
    }

    @PostMapping("/content")
    public String save(@RequestBody Content content){
        return contentService.save(content);
    }

    @GetMapping("/content/title/{param}")
    public List<Content> getContentStartWith(@PathVariable("param") String title){
        return contentService.getContentStartWith(title);
    }

    @DeleteMapping("/content/{id}")
    public String delete(@PathVariable Integer id){
        return contentService.delete(id);
    }

    @GetMapping("/id")
    public List<Content>getById(@RequestParam Integer minId,
                                @RequestParam Integer maxId){
        return contentService.getById(minId,maxId);
    }

    @GetMapping("/content/{id}")
    public Optional<Content> findById(@PathVariable Integer id){
        return contentService.findById(id);
    }
}

测试类代码

package com.example.sixth;

import com.example.sixth.controller.ContentController;
import com.example.sixth.entity.Content;
import com.example.sixth.service.ContentService;
import com.example.sixth.service.ContentServiceImpl;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MockMvcBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

import static org.hamcrest.Matchers.is;
import static org.junit.jupiter.api.Assertions.assertEquals;

@AutoConfigureMockMvc
//@SpringBootTest
public class ContentControllerTest {

    @Autowired
    MockMvc mockMvc;

    @Mock
    ContentService mockService;

    @InjectMocks
    ContentController contentController;

    @BeforeEach
    public void init(){
        MockitoAnnotations.initMocks(this);

        this.mockMvc= MockMvcBuilders.standaloneSetup(mockService).build();
    }

    @Test
    public void testfindall() throws Exception {
        Content content = (Content.builder()
                .id(3)
                .title("SECOND!!")
                .duration(38)
                .location("Bangalore").build());
        List<Content> contentList = new ArrayList<>();
        contentList.add(content);
        Mockito.when(mockService.showAll()).thenReturn(contentList);
        
        mockMvc.perform(MockMvcRequestBuilders.get("/content").contentType(MediaType.APPLICATION_JSON)).andExpect(MockMvcResultMatchers.jsonPath("$.duration",is(content.getDuration())));
//        List<Content> actual=contentController.show();
//        System.out.println(actual.get(0).toString());
//        assertEquals(actual,contentList);
    }
}

注:普通断言测试功能正常,但MockMvc测试触发上述错误


问题原因及修复方案

1. MockMvc初始化错误

standaloneSetup方法需要传入控制器实例,而非Service的Mock对象。原代码传入mockService导致MockMvc无法识别/content的请求映射,出现路径匹配警告。

修复代码:

@BeforeEach
public void init(){
    MockitoAnnotations.initMocks(this);
    // 改为注入控制器实例
    this.mockMvc= MockMvcBuilders.standaloneSetup(contentController).build();
}

2. JSON路径断言错误

控制器show()方法返回List<Content>,对应JSON结构是数组而非单个对象。原断言$.duration是在根对象下查找字段,实际应定位数组第一个元素的属性。

修复代码:

mockMvc.perform(MockMvcRequestBuilders.get("/content").contentType(MediaType.APPLICATION_JSON))
       .andExpect(MockMvcResultMatchers.jsonPath("$[0].duration", is(content.getDuration())));

可选:简化测试配置

使用@WebMvcTest(ContentController.class)替代@AutoConfigureMockMvc,Spring会自动配置MockMvc并仅加载目标控制器组件,配合@MockBean可简化Mock注入:

@WebMvcTest(ContentController.class)
public class ContentControllerTest {

    @Autowired
    MockMvc mockMvc;

    @MockBean
    ContentService mockService;

    @Test
    public void testfindall() throws Exception {
        Content content = Content.builder()
                .id(3)
                .title("SECOND!!")
                .duration(38)
                .location("Bangalore").build();
        List<Content> contentList = new ArrayList<>();
        contentList.add(content);
        Mockito.when(mockService.showAll()).thenReturn(contentList);
        
        mockMvc.perform(MockMvcRequestBuilders.get("/content")
                        .contentType(MediaType.APPLICATION_JSON))
               .andExpect(MockMvcResultMatchers.jsonPath("$[0].duration", is(content.getDuration())));
    }
}

内容的提问来源于stack exchange,提问作者harsh agarwal

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 14:25:04