【问题标题】:UnsupportedMediaTypeException: Content type 'application/octet-stream' not supported for bodyType=java.util.Map<java.lang.String, java.lang.String>))UnsupportedMediaTypeException:bodyType=java.util.Map<java.lang.String, java.lang.String> 不支持内容类型“application/octet-stream”))
【发布时间】:2021-06-27 03:57:29
【问题描述】:

我在为控制器运行 junit 时遇到以下错误。我已经将 content-type 设置为 Json,但错误仍然相同。任何建议可能是什么问题?

错误是

java.lang.AssertionError: expectation "expectNext({response=employee saved Successfully})" failed (expected: onNext({response=employee saved Successfully}); actual: onError(org.springframework.web.reactive.function.UnsupportedMediaTypeException: Content type 'application/octet-stream' not supported for bodyType=java.util.Map<java.lang.String, java.lang.String>))

控制器是

@Slf4j
@Controller
@RequiredArgsConstructor
public class EmployeeController {

    private final EmployeeService employeeService;
    
    @PostMapping(path ="/employees",produces =  APPLICATION_JSON_VALUE)
    public @ResponseBody Mono<Map<String, String>> saveEmployees(@RequestBody List<EmployeeDto> employeeDtos) {
        log.info("Received request to save employees [{}]", employeeDtos);
        return employeeService.saveEmployee(employeeDtos);
    }
}

服务类如下:

@Service
@Slf4j
@RequiredArgsConstructor
public class EmployeeService {

    private final WebClient webClient;

    public Mono<Map<String, String>> saveEmployees(List<EmployeeDto> employeeDtos) {
        return webClient
                .post()
                .uri("/create-employees")
                .contentType(APPLICATION_JSON)
                .bodyValue(employeeDtos)
                .retrieve()
                .bodyToMono(new ParameterizedTypeReference<Map<String, String>>() {
                })
                .doOnError(e -> log.error("Failed to save employees {}: {}", employeeDtos, e));

Junit 如下:

@Slf4j
@SpringBootTest
class EmployeeServiceTest {

private static final WireMockServer wireMockServer = new WireMockServer(wireMockConfig().dynamicPort());

    @Autowired
    private ObjectMapper objectMapper;

    @Autowired
    private EmployeeService employeeService;

    @Test
    void shouldMakeAPostApiCallToSaveEmployee() throws JsonProcessingException {
        var actualemployeeDtos = "....";
        var randomEmployeeDto = ...;
        wireMockServer.stubFor(post("/create-employees")
                .withHeader(CONTENT_TYPE, equalTo(APPLICATION_JSON_VALUE))
                .withHeader(ACCEPT, containing(APPLICATION_JSON_VALUE))
                .withRequestBody(equalToJson(actualemployeeDtos))
                .willReturn(aResponse()
                        .withStatus(OK.value())
                        .withBody("{\"response\": \"employee saved Successfully\"}")));

        StepVerifier
                .create(employeeService.saveEmployee(List.of(randomEmployeeDto)))
                .expectNext(singletonMap("response", "employee saved Successfully"))
                .verifyComplete();
    }
}

【问题讨论】:

    标签: java spring spring-mvc jackson octetstring


    【解决方案1】:

    经过调试,发现连响应头都需要设置content-type作为BodyExtractors类的readWithMessageReaders()方法检查content-type。

    .withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE)
    

    在下面的代码中设置修复了失败的测试用例

    @Test
        void shouldMakeAPostApiCallToSaveEmployee() throws JsonProcessingException {
            var actualemployeeDtos = "....";
            var randomEmployeeDto = ...;
            wireMockServer.stubFor(post("/create-employees")
                    .withHeader(CONTENT_TYPE, equalTo(APPLICATION_JSON_VALUE))
                    .withHeader(ACCEPT, containing(APPLICATION_JSON_VALUE))
                    .withRequestBody(equalToJson(actualemployeeDtos))
                    .willReturn(aResponse()
                            .withHeader(CONTENT_TYPE, APPLICATION_JSON_VALUE)
                            .withStatus(OK.value())
                            .withBody("{\"response\": \"Employees saved Successfully\"}")));
    
            StepVerifier
                    .create(employeeService.saveEmployee(List.of(randomEmployeeDto)))
                    .expectNext(singletonMap("response", "Employees saved Successfully"))
                    .verifyComplete();
        }
    

    【讨论】:

      【解决方案2】:

      在我的情况下,我修复了手动解析包含 json 对象的部分之一的问题

      此代码无效

      @PostMapping(value = "salvaDomanda")
      @ResponseBody
      @ResponseStatus(HttpStatus.CREATED)
      Domanda salvaDomanda(@RequestPart("data")  Domanda domanda,
                        @RequestPart(name = "files", required = false) MultipartFile[] files)
      

      这个

      @PostMapping(value = "salvaDomanda")
      @ResponseBody
      @ResponseStatus(HttpStatus.CREATED)
      Domanda salvaDomanda(@RequestPart("data") String jsonDomanda,
                           @RequestPart(name = "files", required = false) MultipartFile[] files)
              throws ApplicationException, IOException {
          ObjectMapper mapper = new ObjectMapper();
          Domanda domanda = mapper.readValue(jsonDomanda, Domanda.class);
      

      确实如此。 我的 Spring Boot 版本是 2.6.3,带有 java 17

      【讨论】:

        猜你喜欢
        • 2018-10-27
        • 2012-06-30
        • 1970-01-01
        • 1970-01-01
        • 2012-08-23
        • 2012-09-11
        • 2012-05-06
        • 2019-10-16
        • 1970-01-01
        相关资源
        最近更新 更多