1. Overview
1.概述
In this tutorial, we’ll discuss how to test REST services using REST-assured, with a focus on capturing and validating the response data from our REST APIs.
在本教程中,我们将讨论如何使用REST-assured测试REST服务,重点是捕获和验证来自REST API的响应数据。
2. Setup for the Test Class
2.测试班的设置
In previous tutorials, we’ve explored REST-assured in general, and we’ve shown how to manipulate request headers, cookies and parameters.
在之前的教程中,我们已经探讨了REST-assured的总体情况,并展示了如何操作请求头文件、cookies和参数。
Building on this existing setup, we’ve added a simple REST controller, AppController, that internally calls a service, AppService. We’ll use these classes in our test examples.
在现有设置的基础上,我们添加了一个简单的REST控制器,AppController,在内部调用一个服务,AppService。我们将在测试实例中使用这些类。
To create our test class, we need to do a bit more setup. Since we have spring-boot-starter-test in our classpath, we can easily leverage Spring testing utilities.
为了创建我们的测试类,我们需要做更多的设置。由于我们的classpath中有spring-boot-starter-test,我们可以轻松地利用Spring的测试工具。
First, let’s create the skeleton of our AppControllerIntegrationTest class:
首先,让我们创建AppControllerIntegrationTest类的骨架。
@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
public class AppControllerIntegrationTest {
@LocalServerPort
private int port;
private String uri;
@PostConstruct
public void init() {
uri = "http://localhost:" + port;
}
@MockBean
AppService appService;
//test cases
}
In this JUnit test, we annotated our class with a couple of Spring-specific annotations that spin up the application locally in a random available port. In @PostConstruct, we captured the full URI on which we will be making REST calls.
在这个JUnit测试中,我们用几个Spring特有的注解对我们的类进行了注解,在本地随机的可用端口中启动应用程序。在@PostConstruct中,我们捕获了我们将进行REST调用的完整URI。
We also used @MockBean on AppService, as we need to mock method calls on this class.
我们还在AppService上使用了@MockBean,因为我们需要在这个类上模拟方法调用。
3. Validating the JSON Response
3.验证JSON响应
JSON is the most common format used in REST APIs to exchange data. Responses can consist of a single JSON object or an array of JSON objects. We’ll look at both in this section.
JSON是REST API中用来交换数据的最常见格式。响应可以由单个JSON对象或JSON对象的数组组成。我们将在本节中对这两种对象进行研究。
3.1. Single JSON Object
3.1 单个JSON对象
Let’s say we need to test the /movie/{id} endpoint, which returns a Movie JSON object if the id is found.
假设我们需要测试/movie/{id}端点,如果找到id,则返回一个MovieJSON对象。
We’ll mock AppService calls to return some mock data using the Mockito framework:
我们将使用Mockito框架来模拟AppService调用以返回一些模拟数据。
@Test
public void givenMovieId_whenMakingGetRequestToMovieEndpoint_thenReturnMovie() {
Movie testMovie = new Movie(1, "movie1", "summary1");
when(appService.findMovie(1)).thenReturn(testMovie);
get(uri + "/movie/" + testMovie.getId()).then()
.assertThat()
.statusCode(HttpStatus.OK.value())
.body("id", equalTo(testMovie.getId()))
.body("name", equalTo(testMovie.getName()))
.body("synopsis", notNullValue());
}
Above, we first mocked the appService.findMovie(1) call to return an object. Then, we constructed our REST URL in the get() method provided by REST-assured for making GET requests. Finally, we made four assertions.
上面,我们首先模拟了appService.findMovie(1)调用以返回一个对象。然后,我们用REST-assured提供的get()方法构建了我们的REST URL,用于发出GET请求。最后,我们做了四个断言。
First, we checked the response status code and then the body elements. We’re using Hamcrest to assert the expected value.
首先,我们检查了响应状态代码,然后是body元素。我们使用Hamcrest来断言预期值。
Also note that if the response JSON is nested, we can test a nested key by using the dot operator like “key1.key2.key3”.
还要注意的是,如果响应的JSON是嵌套的,我们可以通过使用dot操作符来测试一个嵌套的键,比如“key1.key2.key3”。
3.2. Extracting the JSON Response After Validation
3.2.提取验证后的JSON响应
In some cases, we may need to extract the response after validation, to perform additional operations on it.
在某些情况下,我们可能需要在验证后提取响应,以对其进行额外的操作。
We can extract the JSON response to a class, using the extract() method:
我们可以使用extract()方法,将JSON响应提取为一个类:。
Movie result = get(uri + "/movie/" + testMovie.getId()).then()
.assertThat()
.statusCode(HttpStatus.OK.value())
.extract()
.as(Movie.class);
assertThat(result).isEqualTo(testMovie);
In this example, we directed REST-assured to extract the JSON response to a Movie object and then asserted on the extracted object.
在这个例子中,我们指示REST-assured提取一个Movie对象的JSON响应,然后对提取的对象进行断言。
We can also extract the whole response to a String, using the extract().asString() API:
我们还可以使用extract().asString() API将整个响应提取为字符串:。
String responseString = get(uri + "/movie/" + testMovie.getId()).then()
.assertThat()
.statusCode(HttpStatus.OK.value())
.extract()
.asString();
assertThat(responseString).isNotEmpty();
Finally, we can extract a particular field out of the response JSON as well.
最后,我们也可以从响应的JSON中提取一个特定字段。
Let’s look at a test for a POST API that expects a Movie JSON body and will return the same if inserted successfully:
让我们看看一个POST API的测试,它期望一个Movie JSON主体,如果插入成功,将返回相同的内容。
@Test
public void givenMovie_whenMakingPostRequestToMovieEndpoint_thenCorrect() {
Map<String, String> request = new HashMap<>();
request.put("id", "11");
request.put("name", "movie1");
request.put("synopsis", "summary1");
int movieId = given().contentType("application/json")
.body(request)
.when()
.post(uri + "/movie")
.then()
.assertThat()
.statusCode(HttpStatus.CREATED.value())
.extract()
.path("id");
assertThat(movieId).isEqualTo(11);
}
Above, we first made the request object that we need to POST. We then extracted the id field from the returned JSON response using the path() method.
上面,我们首先制作了我们需要POST的请求对象。然后我们使用path()方法从返回的JSON响应中提取了id字段。
3.3. JSON Array
3.3 JSON数组
We can also verify the response if it’s a JSON array:
如果是一个JSON数组,我们也可以验证响应。
@Test
public void whenCallingMoviesEndpoint_thenReturnAllMovies() {
Set<Movie> movieSet = new HashSet<>();
movieSet.add(new Movie(1, "movie1", "summary1"));
movieSet.add(new Movie(2, "movie2", "summary2"));
when(appService.getAll()).thenReturn(movieSet);
get(uri + "/movies").then()
.statusCode(HttpStatus.OK.value())
.assertThat()
.body("size()", is(2));
}
We again first mocked the appService.getAll() with some data and made a request to our endpoint. We then asserted the statusCode and size of our response array.
我们首先用一些数据模拟了appService.getAll(),并向我们的端点发出了请求。然后我们断言了我们的响应数组的statusCode和size。
This again can be done via extraction:
这也可以通过提取来完成。
Movie[] movies = get(uri + "/movies").then()
.statusCode(200)
.extract()
.as(Movie[].class);
assertThat(movies.length).isEqualTo(2);
4. Validating Headers and Cookies
4.验证头文件和Cookies
We can verify a header or cookie of the response using methods with the same name:
我们可以使用同名的方法验证响应的头或cookie。
@Test
public void whenCallingWelcomeEndpoint_thenCorrect() {
get(uri + "/welcome").then()
.assertThat()
.header("sessionId", notNullValue())
.cookie("token", notNullValue());
}
We can also extract the headers and cookies individually:
我们还可以单独提取头文件和cookies。
Response response = get(uri + "/welcome");
String headerName = response.getHeader("sessionId");
String cookieValue = response.getCookie("token");
assertThat(headerName).isNotBlank();
assertThat(cookieValue).isNotBlank();
5. Validating Files
5.验证文件
If our REST API returns a file, we can use the asByteArray() method to extract the response:
如果我们的REST API返回一个文件,我们可以使用asByteArray()方法来提取响应。
File file = new ClassPathResource("test.txt").getFile();
long fileSize = file.length();
when(appService.getFile(1)).thenReturn(file);
byte[] result = get(uri + "/download/1").asByteArray();
assertThat(result.length).isEqualTo(fileSize);
Here, we first mocked appService.getFile(1) to return a text file that is present in our src/test/resources path. We then made a call to our endpoint and extracted the response in a byte[], which we then asserted to have the expected value.
在这里,我们首先模拟了appService.getFile(1),以返回一个存在于我们src/test/resources路径中的文本文件。然后我们调用了我们的端点,并提取了byte[]中的响应,然后我们断言它具有预期的值。
6. Conclusion
6.结论
In this tutorial, we looked into different ways of capturing and validating responses from our REST APIs using REST-assured.
在本教程中,我们研究了使用REST-assured从我们的REST APIs捕获和验证响应的不同方法。
As usual, the code in this article is available over on Github.
像往常一样,本文中的代码可以在Github上获得over。