如何使用Post方法测试Rest服务上的获取参数

问题描述

我正在尝试测试使用Post方法获取用于处理请求的参数

@RestController
@RequestMapping("api")
public class InnerRestController {

…
    @PostMapping("createList")
    public ItemListId createList(@RequestParam String strListId,@RequestParam String strDate) {


…
        return null;
    }
}

变体1

@RunWith(springrunner.class)
@SpringBoottest(webEnvironment = SpringBoottest.WebEnvironment.RANDOM_PORT)
class InnerRestControllerTest {

    @LocalServerPort
    private int port;

    @Autowired
    private TestRestTemplate restTemplate;

    @Test
    void innerCreatePublishList() {

        String url = "http://localhost:" + this.port;

        String uri = "/api/createList";

        String listStr = "kl";

        String strDate = "10:21";

        URI uriToEndpoint = UriComponentsBuilder
                .fromHttpUrl(url)
                .path(uri)
                .queryParam("strListId",listStr)
                .queryParam("strDate ",strDate)
                .build()
                .encode()
                .toUri();

        ResponseEntity< ItemListId > listIdResponseEntity =
                restTemplate.postForEntity(uri,uriToEndpoint,ItemListId.class);


    }
}

变体2

@Test
void createList() {

        String uri = "/api/createList";

        String listStr = "kl";

        String strDate = "10:21";

    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(uri)
                .queryParam("strListId",strDate);

    Map<String,String> map = new HashMap<>();

    map.put("strListId",listStr);//request parameters
    map.put("strDate",strDate);


    ResponseEntity< ItemListId > listIdResponseEntity =
            restTemplate.postForEntity(uri,map,ItemListId.class);


}

更新_1

在我的项目中,异常是这样处理的:

  • dto
public final class ErrorResponseDto {

    private  String errorMsg;

    private  int status;

    @JsonFormat(shape = JsonFormat.Shape.STRING,pattern = "yyyy-MM-dd hh:mm:ss")
    LocalDateTime timestamp;

...
  • 处理程序
@RestControllerAdvice
public class ExceptionAdviceHandler {

    @ExceptionHandler(value = PublishListException.class)
    public ResponseEntity<ErrorResponseDto> handleGenericpublishListdublicateException(PublishListException e) {

        ErrorResponseDto error = new ErrorResponseDto(e.getMessage());
        error.setTimestamp(LocalDateTime.Now());
        error.setStatus((HttpStatus.CONFLICT.value()));

        return new ResponseEntity<>(error,HttpStatus.CONFLICT);
    }   

}

方法中,如有必要,我会抛出一个特定的异常...

.w.s.m.s.DefaultHandlerExceptionResolver:已解决 [org.springframework.web.bind.MissingServletRequestParameterException: 必需的字符串参数'strListId'不存在]

谁知道错误是什么。请在此处说明您需要添加内容以及原因?

解决方法

让我们来看看postEntity中的declarations

postForEntity(URI url,Object request,Class<T> responseType)
...
postForEntity(String url,Class<T> responseType,Object... uriVariables)

如您所见,第一个参数是URIString with uriVariables,但是第二个参数始终是请求实体。

在第一个变体中,您将uri字符串作为URI,然后将uriToEndpoint作为请求实体进行传递,并假装它是请求对象。正确的解决方案是:

ResponseEntity<ItemListId> listIdResponseEntity =
                restTemplate.postForEntity(uriToEndpoint,null,ItemListId.class);

解决您的评论。

如果服务器以HTTP 409响应,则RestTemplate会引发ErrorResponseDto内容的异常。您可以捕获RestClientResponseException并反序列化存储在异常中的服务器响应。像这样:

try {
  ResponseEntity<ItemListId> listIdResponseEntity =
                restTemplate.postForEntity(uriToEndpoint,ItemListId.class);
  
  ...
} catch(RestClientResponseException e) {
  byte[] errorResponseDtoByteArray  = e.getResponseBodyAsByteArray();
  
  // Deserialize byte[] array using Jackson
}