如何使用 POST 方法测试 REST 服务上获取参数的操作。

huangapple go评论83阅读模式
英文:

How to test getting parameters on the Rest service using the Post method

问题

我正在尝试测试使用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", listStr)
                .queryParam("strDate ", strDate);

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

    map.put("strListId", listStr);//请求参数
    map.put("strDate", strDate);


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


}

Update_1

在我的项目中,异常被处理如下:

  • 数据传输对象
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']

谁知道这个错误是什么。请解释需要在这里添加什么以及为什么?

英文:

I'm trying to test getting parameters for processing a request using the Post method

@RestController
@RequestMapping(&quot;api&quot;)
public class InnerRestController {


    @PostMapping(&quot;createList&quot;)
    public ItemListId createList(@RequestParam String strListId,
@RequestParam String strDate) {



        return null;
    }
}
  • test method

variant 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 = &quot;http://localhost:&quot; + this.port;

        String uri = &quot;/api/createList&quot;;

        String listStr = &quot;kl&quot;;

        String strDate = &quot;10:21&quot;;

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

        ResponseEntity&lt; ItemListId &gt; listIdResponseEntity =
                restTemplate.postForEntity(uri, uriToEndpoint, ItemListId.class);


    }
}

variant 2

@Test
void createList() {

        String uri = &quot;/api/createList&quot;;

        String listStr = &quot;kl&quot;;

        String strDate = &quot;10:21&quot;;

    UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(uri)
                .queryParam(&quot;strListId&quot;, listStr)
                .queryParam(&quot;strDate &quot;, strDate);

    Map&lt;String, String&gt; map = new HashMap&lt;&gt;();

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


    ResponseEntity&lt; ItemListId &gt; listIdResponseEntity =
            restTemplate.postForEntity(uri, map, ItemListId.class);


}

Update_1

In my project exceptions is handled thus:

  • dto
public final class ErrorResponseDto {

	private  String errorMsg;

	private  int status;

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

...
  • handler
@RestControllerAdvice
public class ExceptionAdviceHandler {

	@ExceptionHandler(value = PublishListException.class)
	public ResponseEntity&lt;ErrorResponseDto&gt; handleGenericPublishListDublicateException(PublishListException e) {

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

		return new ResponseEntity&lt;&gt;(error, HttpStatus.CONFLICT);
	}	

}

In methods, where necessary, I throw a specific exception...

> .w.s.m.s.DefaultHandlerExceptionResolver : Resolved
> [org.springframework.web.bind.MissingServletRequestParameterException:
> Required String parameter 'strListId' is not present]

Who knows what the error is. Please explain what you need to add here and why ?

答案1

得分: 1

让我们来看一下关于 postEntity声明

postForEntity(URI url, Object request, Class&lt;T&gt; responseType)
...
postForEntity(String url, Object request, Class&lt;T&gt; responseType, Object... uriVariables)

正如您所见,第一个参数可以是 URI 或带有 uriVariablesString,但第二个参数始终是请求实体。

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

ResponseEntity&lt;ItemListId&gt; listIdResponseEntity =
                restTemplate.postForEntity(uriToEndpoint, null, ItemListId.class);

回复您的评论。

如果服务器以 HTTP 409 响应,RestTemplate 将抛出带有您的 ErrorResponseDto 内容的异常。您可以捕获 RestClientResponseException 并反序列化存储在异常中的服务器响应。类似这样:

try {
  ResponseEntity&lt;ItemListId&gt; listIdResponseEntity =
                restTemplate.postForEntity(uriToEndpoint, null, 
  ItemListId.class);
  
  ...
} catch(RestClientResponseException e) {
  byte[] errorResponseDtoByteArray  = e.getResponseBodyAsByteArray();
  
  // 使用 Jackson 反序列化 byte[] 数组
}
英文:

Let's take a look on declarations of postEntity:

postForEntity(URI url, Object request, Class&lt;T&gt; responseType)
...
postForEntity(String url, Object request, Class&lt;T&gt; responseType, Object... uriVariables)

As you can see, first argument is either URI or String with uriVariables, but second argument is always request entity.

In you first variant you put uri String as URI and then pass uriToEndpoint as request entity, pretending that it is request object. Correct solution will be:

ResponseEntity&lt;ItemListId&gt; listIdResponseEntity =
                restTemplate.postForEntity(uriToEndpoint, null, ItemListId.class);

Addressing your comments.

If server responded with HTTP 409, RestTemplate will throw exception with content of your ErrorResponseDto. You can catch RestClientResponseException and deserialize server response stored in exception. Something like this:

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

huangapple
  • 本文由 发表于 2020年8月22日 03:25:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/63528976.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定