Spring Boot 2.7集成JUnit测试时出现‘Content type not set’错误的解决方案咨询
问题根源分析
嘿,我一眼就揪出问题所在了——你的测试逻辑和Controller的实际执行路径完全不匹配!
看你测试代码里的这段mock:
when(employeeService.findByEmail(any(String.class))).thenReturn(Optional.of(employee));
这相当于模拟了「数据库里已经存在这个邮箱的员工」的场景,此时Controller会触发这段分支:
if (!employeeDb.isEmpty()) { return new ResponseEntity<>(HttpStatus.CONFLICT); }
这个返回的ResponseEntity只带了409冲突状态码,既没有响应体,也没设置Content-Type。但你的测试却硬要断言:
.andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
一边期望200成功状态,一边检查Content-Type,这不报错才怪——409响应根本就没这个属性啊!
解决方案(两种场景二选一)
根据你实际的测试目标,有两个修改方向:
场景1:测试「添加重复员工返回冲突」
如果你的本意就是验证重复添加的冲突场景,直接调整测试的断言逻辑就行:
@Test void addEmployee_duplicateEmail_returnsConflict() throws Exception { when(employeeService.findByEmail(any(String.class))).thenReturn(Optional.of(employee)); ObjectMapper objectMapper = new ObjectMapper(); String json = objectMapper.writeValueAsString(employeeDto); mockMvc.perform( MockMvcRequestBuilders .post(REST_URL) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .characterEncoding("utf-8") .content(json) ) .andExpect(status().isConflict()); // 改成期望409状态码 // 删掉所有检查响应体的断言,因为冲突响应没有body }
场景2:测试「添加新员工成功」
如果本来是想验证正常添加的成功流程,那得修改mock逻辑,让findByEmail返回空的Optional,这样Controller才会走保存分支,返回带Content-Type的200响应:
@Test void addEmployee_newEmployee_returnsOk() throws Exception { when(employeeService.save(employeeDto.toEmployee())).thenReturn(employee); // 这里改一下:返回空Optional,表示数据库中无该员工 when(employeeService.findByEmail(any(String.class))).thenReturn(Optional.empty()); ObjectMapper objectMapper = new ObjectMapper(); String json = objectMapper.writeValueAsString(employeeDto); mockMvc.perform( MockMvcRequestBuilders .post(REST_URL) .contentType(MediaType.APPLICATION_JSON) .accept(MediaType.APPLICATION_JSON) .characterEncoding("utf-8") .content(json) ) .andExpect(status().isOk()) .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) .andExpect(jsonPath("$.firstname", is(employee.getFirstname()))) .andExpect(jsonPath("$.lastname", is(employee.getLastname()))) .andExpect(jsonPath("$.email", is(employee.getEmail()))); }
额外优化(可选)
如果希望冲突响应也能带上Content-Type,可以调整Controller的返回逻辑:
if (!employeeDb.isEmpty()) { return ResponseEntity.status(HttpStatus.CONFLICT) .contentType(MediaType.APPLICATION_JSON) .build(); }
不过这不是必须的,完全看你的业务需求。
内容的提问来源于stack exchange,提问作者poub 770
相关产品推荐
相关产品推荐

