使用 TestRestTemplate 测试接口
TestRestTemplate
和 RestTemplate
的用法类似,其本质上就是封装了 RestTemplate
专供集成测试使用。
只需要在测试类上使用 @SpringBootTest
注解,并且将 webEnvironment 字段指定为 SpringBootTest.WebEnvironment.RANDOM_PORT
或 SpringBootTest.WebEnvironment.DEFINED_PORT
,执行测试方法时就会自动注入 TestRestTemplate
实例。
假设有如下 GET 和 POST 接口:
请求类型 | URL | 说明 |
---|---|---|
GET | /hello | 没有参数 |
GET | /hello/{name} | 从 URL 的 Path 中获取参数 |
POST | /hello | 从 POST 请求的 Body 中获取参数 |
POST | /hello/from-header | 从 Header 中获取参数 |
对应的 HelloController
代码如下:
java
package me.liujiajia.springboot.advanced.rest.template.controller;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.*;
/**
* @author 佳佳
*/
@RestController
@RequiredArgsConstructor
@RequestMapping("hello")
public class HelloController {
@GetMapping
public String sayHello() {
return "Hello,World!";
}
@GetMapping("{name}")
public String sayHello(@PathVariable String name) {
return String.format("Hello,%s!", name);
}
@PostMapping
public String sayHello(@RequestBody UserInfo userInfo) {
return String.format("Hello,%s!", userInfo.getName());
}
@PostMapping("from-header")
public String sayHelloFromHeader(@RequestHeader String name) {
return String.format("Hello,%s!", name);
}
@Data
public static class UserInfo {
private String name;
}
}
对应的测试类 HelloControllerTest
如下:
java
package me.liujiajia.springboot.advanced.rest.template.controller;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.web.client.TestRestTemplate;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class HelloControllerTest {
public static final String NAME = "JiaJia";
/**
* WebEnvironment.RANDOM_PORT 和 WebEnvironment.DEFINED_PORT 时才会自动注入
* 详见 TestRestTemplateContextCustomizer.customizeContext() 方法
*/
@Autowired
private TestRestTemplate testRestTemplate;
@Test
void sayHello() {
ResponseEntity<String> responseEntity = testRestTemplate.getForEntity("/hello", String.class);
Assertions.assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
Assertions.assertEquals(responseEntity.getBody(), "Hello,World!");
}
@Test
void sayHelloWithName() {
ResponseEntity<String> responseEntity = testRestTemplate.getForEntity(String.format("/hello/%s", NAME),
String.class);
Assertions.assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
Assertions.assertEquals(responseEntity.getBody(), String.format("Hello,%s!", NAME));
}
@Test
void sayHelloWithUserInfo() {
HelloController.UserInfo userInfo = new HelloController.UserInfo();
userInfo.setName(NAME);
ResponseEntity<String> responseEntity = testRestTemplate.postForEntity("/hello", userInfo, String.class);
Assertions.assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
Assertions.assertEquals(responseEntity.getBody(), String.format("Hello,%s!", NAME));
}
@Test
void sayHelloWithHeader() {
HttpHeaders headers = new HttpHeaders();
headers.add("name", NAME);
HttpEntity<Object> httpEntity = new HttpEntity<>(headers);
ResponseEntity<String> responseEntity = testRestTemplate.postForEntity("/hello/from-header",
httpEntity, String.class);
Assertions.assertEquals(responseEntity.getStatusCode(), HttpStatus.OK);
Assertions.assertEquals(responseEntity.getBody(), String.format("Hello,%s!", NAME));
}
}
上面的示例中分别调用了 TestRestTemplate
的 getForEntity()
和 postForEntity()
方法获取 ResponseEntity
,另外还可通过传递 HttpEntity<>
类型的参数设置请求的 Header 。
除此之外 TestRestTemplate
还有其他几种类型的 HTTP 请求对应的方法,比较特殊的是 exchange()
和 execute()
,这两个方法支持发送所有类型的请求。
另外,可以在测试目录的 resources 下的 application.yml 文件中指定测试时专用的配置。
比如下面的配置就修改了 org.springframework.web.client 包下的日志级别为 DEBUG 以显示更多的请求信息:
yaml
logging:
level:
root: INFO
org.springframework.web.client: DEBUG
此时运行测试方法会看到类似如下的日志:
java
2022-11-04 16:42:04.181 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : HTTP GET http://localhost:63618/hello
2022-11-04 16:42:04.183 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Accept=[text/plain, application/json, application/*+json, */*]
2022-11-04 16:42:04.258 INFO 13356 --- [o-auto-1-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/] : Initializing Spring DispatcherServlet 'dispatcherServlet'
2022-11-04 16:42:04.258 INFO 13356 --- [o-auto-1-exec-1] o.s.web.servlet.DispatcherServlet : Initializing Servlet 'dispatcherServlet'
2022-11-04 16:42:04.258 INFO 13356 --- [o-auto-1-exec-1] o.s.web.servlet.DispatcherServlet : Completed initialization in 0 ms
2022-11-04 16:42:04.310 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Response 200 OK
2022-11-04 16:42:04.311 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Reading to [java.lang.String] as "text/plain;charset=UTF-8"
2022-11-04 16:42:04.334 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : HTTP POST http://localhost:63618/hello
2022-11-04 16:42:04.335 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Accept=[text/plain, application/json, application/*+json, */*]
2022-11-04 16:42:04.368 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Writing [HelloController.UserInfo(name=JiaJia)] with org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
2022-11-04 16:42:04.423 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Response 200 OK
2022-11-04 16:42:04.424 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Reading to [java.lang.String] as "text/plain;charset=UTF-8"
2022-11-04 16:42:04.429 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : HTTP POST http://localhost:63618/hello/from-header
2022-11-04 16:42:04.429 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Accept=[text/plain, application/json, application/*+json, */*]
2022-11-04 16:42:04.437 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Response 200 OK
2022-11-04 16:42:04.438 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Reading to [java.lang.String] as "text/plain;charset=UTF-8"
2022-11-04 16:42:04.444 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : HTTP GET http://localhost:63618/hello/JiaJia
2022-11-04 16:42:04.445 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Accept=[text/plain, application/json, application/*+json, */*]
2022-11-04 16:42:04.451 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Response 200 OK
2022-11-04 16:42:04.451 DEBUG 13356 --- [ main] o.s.web.client.RestTemplate : Reading to [java.lang.String] as "text/plain;charset=UTF-8"