Saya baru sahaja mengumumkan kursus Learn Spring yang baru , yang berfokus pada asas-asas Spring 5 dan Spring Boot 2:
>> SEMAK KURSUS1. Pengenalan
REST-assured dirancang untuk mempermudah pengujian dan pengesahan REST API dan sangat dipengaruhi oleh teknik pengujian yang digunakan dalam bahasa dinamik seperti Ruby dan Groovy.
Perpustakaan mempunyai sokongan padu untuk HTTP, bermula dengan kata kerja dan operasi HTTP standard, tetapi juga melampaui asas-asas ini.
Dalam panduan ini, kami akan meneroka REST dan kami akan menggunakan Hamcrest untuk membuat penegasan. Sekiranya anda belum biasa dengan Hamcrest, anda harus terlebih dahulu mengikuti tutorial: Menguji dengan Hamcrest.
Juga, untuk mengetahui mengenai kes penggunaan yang lebih maju yang dijamin REST, lihat artikel kami yang lain:
- KESELAMATAN dengan Groovy
- Pengesahan Skema JSON dengan jaminan REST
- Parameter, Tajuk dan Kuki dengan jaminan REST
Sekarang mari kita selami dengan contoh mudah.
2. Ujian Contoh Ringkas
Sebelum kita memulakan, pastikan ujian kami mempunyai import statik berikut:
io.restassured.RestAssured.* io.restassured.matcher.RestAssuredMatchers.* org.hamcrest.Matchers.*
Kami memerlukannya agar ujian mudah dilakukan dan mempunyai akses mudah ke API utama.
Sekarang, mari kita mulakan dengan contoh mudah - sistem pertaruhan asas yang mendedahkan beberapa data untuk permainan:
{ "id": "390", "data": { "leagueId": 35, "homeTeam": "Norway", "visitingTeam": "England", }, "odds": [{ "price": "1.30", "name": "1" }, { "price": "5.25", "name": "X" }] }
Katakan bahawa ini adalah tindak balas JSON dari memukul API yang digunakan secara tempatan - // localhost: 8080 / events? Id = 390. :
Sekarang mari kita menggunakan jaminan REST untuk mengesahkan beberapa ciri menarik dari JSON:
@Test public void givenUrl_whenSuccessOnGetsResponseAndJsonHasRequiredKV_thenCorrect() { get("/events?id=390").then().statusCode(200).assertThat() .body("data.leagueId", equalTo(35)); }
Jadi, apa yang kita lakukan di sini adalah - kita mengesahkan bahawa panggilan kepada titik akhir / acara id = 390? Respon dengan badan yang mengandungi rentetan JSON yang IDLiga daripada data objek ialah 35.
Mari lihat contoh yang lebih menarik. Katakan anda ingin mengesahkan bahawa pelbagai kemungkinan mempunyai rekod dengan harga 1.30 dan 5.25 :
@Test public void givenUrl_whenJsonResponseHasArrayWithGivenValuesUnderKey_thenCorrect() { get("/events?id=390").then().assertThat() .body("odds.price", hasItems("1.30", "5.25")); }
3. Persediaan yang dijamin REST
Sekiranya alat pergantungan kegemaran anda adalah Maven, kami menambahkan kebergantungan berikut dalam fail pom.xml :
io.rest-assured rest-assured 3.3.0 test
Untuk mendapatkan versi terkini, ikuti pautan ini.
REST-yakin mengambil kesempatan daripada kekuatan Hamcrest matchers untuk melaksanakan penegasannya, jadi kami juga harus memasukkan kebergantungan itu:
org.hamcrest hamcrest-all 2.1
Versi terkini akan sentiasa tersedia di pautan ini.
4. Pengesahan Akar JSON Tanpa Nama
Pertimbangkan array yang terdiri daripada primitif dan bukan objek:
[1, 2, 3]
Ini disebut root JSON tanpa nama, yang bermaksud bahawa ia tidak mempunyai pasangan nilai-kunci namun ia masih merupakan data JSON yang sah.
Kita dapat menjalankan pengesahan dalam senario seperti itu dengan menggunakan $
simbol atau String kosong (“”) sebagai jalan. Andaikan kami mendedahkan perkhidmatan di atas melalui // localhost: 8080 / json maka kami dapat mengesahkannya seperti ini dengan jaminan REST:
when().get("/json").then().body("$", hasItems(1, 2, 3));
atau seperti ini:
when().get("/json").then().body("", hasItems(1, 2, 3));
5. Terapung dan Berganda
Apabila kita mula menggunakan jaminan REST untuk menguji perkhidmatan REST, kita perlu memahami bahawa nombor titik terapung dalam respons JSON dipetakan ke apungan jenis primitif .
Penggunaan jenis apungan tidak dapat ditukar ganti dengan dua kali ganda seperti yang berlaku untuk banyak senario di java.
Contohnya adalah respons ini:
{ "odd": { "price": "1.30", "ck": 12.2, "name": "1" } }
anggap kita menjalankan ujian berikut pada nilai ck :
get("/odd").then().assertThat().body("odd.ck", equalTo(12.2));
Ujian ini akan gagal walaupun nilai yang kita uji sama dengan nilai dalam tindak balas. Ini kerana kita membandingkan dengan dua kali lipat daripada mengambang .
To make it work, we have to explicitly specify the operand to the equalTo matcher method as a float, like so:
get("/odd").then().assertThat().body("odd.ck", equalTo(12.2f));
6. Specifying the Request Method
Typically, we would perform a request by calling a method such as get(), corresponding to the request method we want to use.
In addition, we can also specify the HTTP verb using the request() method:
@Test public void whenRequestGet_thenOK(){ when().request("GET", "/users/eugenp").then().statusCode(200); }
The example above is equivalent to using get() directly.
Similarly, we can send HEAD, CONNECT and OPTIONS requests:
@Test public void whenRequestHead_thenOK() { when().request("HEAD", "/users/eugenp").then().statusCode(200); }
POST request also follows a similar syntax and we can specify the body by using the with() and body() methods.
Therefore, to create a new Odd by sending a POST request:
@Test public void whenRequestedPost_thenCreated() { with().body(new Odd(5.25f, 1, 13.1f, "X")) .when() .request("POST", "/odds/new") .then() .statusCode(201); }
The Odd object sent as body will automatically be converted to JSON. We can also pass any String that we want to send as our POSTbody.
7. Default Values Configuration
We can configure a lot of default values for the tests:
@Before public void setup() { RestAssured.baseURI = "//api.github.com"; RestAssured.port = 443; }
Here, we're setting a base URI and port for our requests. Besides these, we can also configure the base path, root pat, and authentication.
Note: we can also reset to the standard REST-assured defaults by using:
RestAssured.reset();
8. Measure Response Time
Let's see how we can measure the response time using the time() and timeIn() methods of the Response object:
@Test public void whenMeasureResponseTime_thenOK() { Response response = RestAssured.get("/users/eugenp"); long timeInMS = response.time(); long timeInS = response.timeIn(TimeUnit.SECONDS); assertEquals(timeInS, timeInMS/1000); }
Note that:
- time() is used to get response time in milliseconds
- timeIn() is used to get response time in the specified time unit
8.1. Validate Response Time
We can also validate the response time – in milliseconds – with the help of simple longMatcher:
@Test public void whenValidateResponseTime_thenSuccess() { when().get("/users/eugenp").then().time(lessThan(5000L)); }
If we want to validate the response time in a different time unit, then we'll use the time() matcher with a second TimeUnit parameter:
@Test public void whenValidateResponseTimeInSeconds_thenSuccess(){ when().get("/users/eugenp").then().time(lessThan(5L),TimeUnit.SECONDS); }
9. XML Response Verification
Not only can it validate a JSON response, itcan validate XML as well.
Let's assume we make a request to //localhost:8080/employees and we get the following response:
Jane Daisy f
We can verify that the first-name is Jane like so:
@Test public void givenUrl_whenXmlResponseValueTestsEqual_thenCorrect() { post("/employees").then().assertThat() .body("employees.employee.first-name", equalTo("Jane")); }
We can also verify that all values match our expected values by chaining body matchers together like so:
@Test public void givenUrl_whenMultipleXmlValuesTestEqual_thenCorrect() { post("/employees").then().assertThat() .body("employees.employee.first-name", equalTo("Jane")) .body("employees.employee.last-name", equalTo("Daisy")) .body("employees.employee.sex", equalTo("f")); }
Or using the shorthand version with variable arguments:
@Test public void givenUrl_whenMultipleXmlValuesTestEqualInShortHand_thenCorrect() { post("/employees") .then().assertThat().body("employees.employee.first-name", equalTo("Jane"),"employees.employee.last-name", equalTo("Daisy"), "employees.employee.sex", equalTo("f")); }
10. XPath for XML
We can also verify our responses using XPath. Consider the example below that executes a matcher on the first-name:
@Test public void givenUrl_whenValidatesXmlUsingXpath_thenCorrect() { post("/employees").then().assertThat(). body(hasXPath("/employees/employee/first-name", containsString("Ja"))); }
XPath also accepts an alternate way of running the equalTo matcher:
@Test public void givenUrl_whenValidatesXmlUsingXpath2_thenCorrect() { post("/employees").then().assertThat() .body(hasXPath("/employees/employee/first-name[text()='Jane']")); }
11. Logging Test Details
11.1. Log Request Details
First, let's see how to log entire request details using log().all():
@Test public void whenLogRequest_thenOK() { given().log().all() .when().get("/users/eugenp") .then().statusCode(200); }
This will log something like this:
Request method: GET Request URI: //api.github.com:443/users/eugenp Proxy: Request params: Query params: Form params: Path params: Multiparts: Headers: Accept=*/* Cookies: Body:
To log only specific parts of the request, we have the log() method in combination with params(), body(), headers(), cookies(), method(), path() eg log.().params().
Note that other libraries or filters used may alter what's actually sent to the server, so this should only be used to log the initial request specification.
11.2. Log Response Details
Similarly, we can log the response details.
In the following example we're logging the response body only:
@Test public void whenLogResponse_thenOK() { when().get("/repos/eugenp/tutorials") .then().log().body().statusCode(200); }
Sample output:
{ "id": 9754983, "name": "tutorials", "full_name": "eugenp/tutorials", "private": false, "html_url": "//github.com/eugenp/tutorials", "description": "The \"REST With Spring\" Course: ", "fork": false, "size": 72371, "license": { "key": "mit", "name": "MIT License", "spdx_id": "MIT", "url": "//api.github.com/licenses/mit" }, ... }
11.3. Log Response if Condition Occurred
We also have the option of logging the response only if an error occurred or the status code matches a given value:
@Test public void whenLogResponseIfErrorOccurred_thenSuccess() { when().get("/users/eugenp") .then().log().ifError(); when().get("/users/eugenp") .then().log().ifStatusCodeIsEqualTo(500); when().get("/users/eugenp") .then().log().ifStatusCodeMatches(greaterThan(200)); }
11.4. Log if Validation Failed
We can also log both request and response only if our validation failed:
@Test public void whenLogOnlyIfValidationFailed_thenSuccess() { when().get("/users/eugenp") .then().log().ifValidationFails().statusCode(200); given().log().ifValidationFails() .when().get("/users/eugenp") .then().statusCode(200); }
Dalam contoh ini, kami ingin mengesahkan bahawa kod status adalah 200. Hanya jika ini gagal, permintaan dan respons akan dicatat.
12. Kesimpulannya
Dalam tutorial ini, kami telah meneroka kerangka yang dijamin REST dan melihat ciri terpentingnya yang dapat kami gunakan untuk menguji perkhidmatan RESTful kami dan mengesahkan respons mereka.
Pelaksanaan penuh semua contoh dan coretan kod ini terdapat dalam projek GitHub yang dijamin REST.
Bahagian bawah Jackson