英文:
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("api")
public class InnerRestController {
…
@PostMapping("createList")
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 = "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);
}
}
variant 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);//request parameters
map.put("strDate", strDate);
ResponseEntity< ItemListId > 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 = "yyyy-MM-dd hh:mm:ss")
LocalDateTime timestamp;
...
- handler
@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);
}
}
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<T> responseType)
...
postForEntity(String url, Object request, Class<T> responseType, Object... uriVariables)
正如您所见,第一个参数可以是 URI
或带有 uriVariables
的 String
,但第二个参数始终是请求实体。
在您的第一个变体中,您将 uri
字符串作为 URI,然后将 uriToEndpoint
作为请求实体传递,假装它是请求对象。正确的解决方案应该是:
ResponseEntity<ItemListId> listIdResponseEntity =
restTemplate.postForEntity(uriToEndpoint, null, ItemListId.class);
回复您的评论。
如果服务器以 HTTP 409 响应,RestTemplate
将抛出带有您的 ErrorResponseDto
内容的异常。您可以捕获 RestClientResponseException
并反序列化存储在异常中的服务器响应。类似这样:
try {
ResponseEntity<ItemListId> 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<T> responseType)
...
postForEntity(String url, Object request, Class<T> 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<ItemListId> 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<ItemListId> listIdResponseEntity =
restTemplate.postForEntity(uriToEndpoint, null,
ItemListId.class);
...
} catch(RestClientResponseException e) {
byte[] errorResponseDtoByteArray = e.getResponseBodyAsByteArray();
// Deserialize byte[] array using Jackson
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论