MockMVC测试POST接口预期201却返回404的问题求助
问题:MockMVC测试POST /answers接口返回404错误
原本尝试编写Rest Docs时遇到大量错误,转而进行MockMVC测试,目标是让POST /answers接口返回201状态码,但实际测试始终得到404错误,即使简化控制器代码仅返回201状态码也无法解决。
测试类代码
import com.google.gson.Gson; 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.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import preproject.underdog.answer.dto.answer.AnswerPostDto; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(value = AnswerController.class) //@AutoConfigureRestDocs @MockBean(JpaMetamodelMappingContext.class) public class AnswerController { @Autowired private MockMvc mockMvc; @Autowired private Gson gson; @Test @DisplayName("답변 글 작성 테스트") void postAnswer() throws Exception { AnswerPostDto post = new AnswerPostDto("테스트", 1L, 1L); String content = gson.toJson(post); ResultActions actions = mockMvc.perform( post("/answers") .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) .content(content) ); actions .andExpect(status().isCreated()); }
控制器类代码
import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import preproject.underdog.answer.dto.answer.AnswerPostDto; import preproject.underdog.answer.dto.answer.AnswerRespDto; import preproject.underdog.answer.mapper.AnswerMapper; import preproject.underdog.answer.service.AnswerService; import javax.validation.Valid; import java.time.LocalDateTime; @RestController @RequestMapping("/answers") @Validated @RequiredArgsConstructor public class AnswerController { private final AnswerService answerService; private final AnswerMapper answerMapper; @PostMapping public ResponseEntity postAnswer(@Valid @RequestBody AnswerPostDto answerPostDto) { AnswerRespDto answerRespDto = new AnswerRespDto(1L,"테스트",1L,1L,1L, LocalDateTime.of(2023, 4, 3, 3, 3, 0),LocalDateTime.of(2023, 4, 3, 3, 3, 0)); return new ResponseEntity<>(answerRespDto, HttpStatus.CREATED); } }
测试日志
MockHttpServletRequest: HTTP Method = POST Request URI = /answers Parameters = {} Headers = [Content-Type:"application/json;charset=UTF-8", Accept:"application/json", Content-Length:"49"] Body = {"content":"테스트","userId":1,"questionId":1} Session Attrs = {} Handler: Type = org.springframework.web.servlet.resource.ResourceHttpRequestHandler Async: Async started = false Async result = null Resolved Exception: Type = null ModelAndView: View name = null View = null Model = null FlashMap: Attributes = null MockHttpServletResponse: Status = 404 Error message = null Headers = [Vary:"Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"] Content type = null Body = Forwarded URL = null Redirected URL = null Cookies = []
简化后的控制器代码
@PostMapping public ResponseEntity postAnswer(@Valid @RequestBody AnswerPostDto answerPostDto) { return new ResponseEntity<>(HttpStatus.CREATED); }
问题原因及解决方案
核心问题是测试类与实际控制器类同名(均为AnswerController),导致@WebMvcTest(value = AnswerController.class)加载的是测试类自身,而非实际处理请求的控制器类,因此无法匹配/answers接口路径,返回404。
解决步骤:
- 重命名测试类:将测试类名称改为
AnswerControllerTest,与控制器类区分开。 - 确保导入正确的控制器类:测试类中
@WebMvcTest注解指向实际的AnswerController,并确认导入包路径正确。
修改后的测试类示例:
import com.google.gson.Gson; 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.WebMvcTest; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.data.jpa.mapping.JpaMetamodelMappingContext; import org.springframework.http.MediaType; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.ResultActions; import preproject.underdog.answer.dto.answer.AnswerPostDto; // 确保导入实际的控制器类 import preproject.underdog.answer.controller.AnswerController; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; @WebMvcTest(AnswerController.class) @MockBean(JpaMetamodelMappingContext.class) // 测试类名修改为AnswerControllerTest public class AnswerControllerTest { @Autowired private MockMvc mockMvc; @Autowired private Gson gson; @Test @DisplayName("답변 글 작성 테스트") void postAnswer() throws Exception { AnswerPostDto post = new AnswerPostDto("테스트", 1L, 1L); String content = gson.toJson(post); ResultActions actions = mockMvc.perform( post("/answers") .accept(MediaType.APPLICATION_JSON) .contentType(MediaType.APPLICATION_JSON) .content(content) ); actions.andExpect(status().isCreated()); } }
额外检查点:
- 确认控制器类在Spring Boot的默认扫描包范围内,若不在,可通过
@WebMvcTest的basePackages属性指定扫描路径。
内容的提问来源于stack exchange,提问作者Simba
相关产品推荐
相关产品推荐

