Panduan untuk REST-terjamin

Jackson Top

Saya baru saja mengumumkan kursus Learn Spring baru , yang berfokus pada dasar-dasar Spring 5 dan Spring Boot 2:

>> LIHAT KURSUSnya

1. Perkenalan

REST-terjamin dirancang untuk menyederhanakan pengujian dan validasi REST API dan sangat dipengaruhi oleh teknik pengujian yang digunakan dalam bahasa dinamis seperti Ruby dan Groovy.

Pustaka memiliki dukungan yang kuat untuk HTTP, tentu saja dimulai dengan kata kerja dan operasi HTTP standar, tetapi juga melampaui dasar-dasar ini.

Dalam panduan ini, kita akan menjelajahi REST-terjamin dan kita akan menggunakan Hamcrest untuk melakukan pernyataan. Jika Anda belum terbiasa dengan Hamcrest, Anda harus terlebih dahulu mempelajari tutorial: Menguji dengan Hamcrest.

Juga, untuk mempelajari tentang kasus penggunaan lanjutan dari REST-terjamin, lihat artikel kami yang lain:

  • Yakinlah dengan Groovy
  • Validasi Skema JSON dengan REST-terjamin
  • Parameter, Header, dan Cookies dengan REST-terjamin

Sekarang mari selami dengan contoh sederhana.

2. Tes Contoh Sederhana

Sebelum kita mulai, mari pastikan bahwa pengujian kita memiliki impor statis berikut:

io.restassured.RestAssured.* io.restassured.matcher.RestAssuredMatchers.* org.hamcrest.Matchers.*

Kami memerlukannya agar pengujian tetap sederhana dan memiliki akses mudah ke API utama.

Sekarang, mari kita mulai dengan contoh sederhana - sistem taruhan dasar yang mengekspos beberapa data untuk permainan:

{ "id": "390", "data": { "leagueId": 35, "homeTeam": "Norway", "visitingTeam": "England", }, "odds": [{ "price": "1.30", "name": "1" }, { "price": "5.25", "name": "X" }] }

Misalkan ini adalah respons JSON dari mengenai API yang diterapkan secara lokal - // localhost: 8080 / events? Id = 390. :

Sekarang mari gunakan REST -ured untuk memverifikasi beberapa fitur menarik dari respons JSON:

@Test public void givenUrl_whenSuccessOnGetsResponseAndJsonHasRequiredKV_thenCorrect() { get("/events?id=390").then().statusCode(200).assertThat() .body("data.leagueId", equalTo(35)); }

Jadi, yang kami lakukan di sini adalah - kami memverifikasi bahwa panggilan ke endpoint / events? Id = 390 merespons dengan body yang berisi JSON String yang leagueIdnya dari objek data adalah 35.

Mari kita lihat contoh yang lebih menarik. Katakanlah Anda ingin memverifikasi bahwa odds array memiliki catatan 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. Setup terjamin REST

Jika alat ketergantungan favorit Anda adalah Maven, kami menambahkan ketergantungan berikut di file pom.xml :

 io.rest-assured rest-assured 3.3.0 test 

Untuk mendapatkan versi terbaru, ikuti tautan ini.

REST -ured memanfaatkan kekuatan pencocok Hamcrest untuk melakukan pernyataannya, jadi kita harus menyertakan ketergantungan itu juga:

 org.hamcrest hamcrest-all 2.1 

Versi terbaru akan selalu tersedia di tautan ini.

4. Validasi Root JSON Anonim

Pertimbangkan array yang terdiri dari primitif daripada objek:

[1, 2, 3]

Ini disebut root JSON anonim, artinya tidak memiliki pasangan nilai kunci, namun tetap merupakan data JSON yang valid.

Kita dapat menjalankan validasi dalam skenario seperti itu dengan menggunakan $simbol atau String kosong ("") sebagai jalur. Asumsikan kita mengekspos layanan di atas melalui // localhost: 8080 / json kemudian kita dapat memvalidasinya seperti ini dengan REST -ured:

when().get("/json").then().body("$", hasItems(1, 2, 3));

atau seperti ini:

when().get("/json").then().body("", hasItems(1, 2, 3));

5. Mengapung dan Ganda

Saat kita mulai menggunakan REST -ured untuk menguji layanan REST kita, kita perlu memahami bahwa angka floating point dalam respons JSON dipetakan ke float tipe primitif .

Penggunaan tipe float tidak dapat dipertukarkan dengan double seperti pada banyak skenario di java.

Contoh kasusnya adalah tanggapan ini:

{ "odd": { "price": "1.30", "ck": 12.2, "name": "1" } }

asumsikan kita menjalankan tes berikut pada nilai ck :

get("/odd").then().assertThat().body("odd.ck", equalTo(12.2));

Tes ini akan gagal meskipun nilai yang kita uji sama dengan nilai dalam respons. Ini karena kita membandingkan dengan double daripada float .

Untuk membuatnya berfungsi, kita harus secara eksplisit menentukan operand ke metode matcher equalTo sebagai float , seperti:

get("/odd").then().assertThat().body("odd.ck", equalTo(12.2f));

6. Menentukan Metode Permintaan

Biasanya, kita akan melakukan permintaan dengan memanggil metode seperti get (), sesuai dengan metode permintaan yang ingin kita gunakan.

Selain itu, kami juga dapat menentukan HTTP kata kerja menggunakan () permintaan metode :

@Test public void whenRequestGet_thenOK(){ when().request("GET", "/users/eugenp").then().statusCode(200); }

Contoh di atas sama dengan menggunakan get () secara langsung.

Demikian pula, kami dapat mengirim permintaan HEAD , CONNECT , dan OPTIONS :

@Test public void whenRequestHead_thenOK() { when().request("HEAD", "/users/eugenp").then().statusCode(200); }

Permintaan POST juga mengikuti sintaks yang serupa dan kita dapat menentukan body dengan menggunakan metode with () dan body () .

Oleh karena itu, untuk membuat Ganjil baru dengan mengirimkan permintaan POST :

@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 objek dikirim sebagai tubuh secara otomatis akan dikonversi ke JSON. Kami juga dapat mengirimkan String apa pun yang ingin kami kirim sebagai badan POST kami .

7. Konfigurasi Nilai Default

Kami dapat mengonfigurasi banyak nilai default untuk pengujian:

@Before public void setup() { RestAssured.baseURI = "//api.github.com"; RestAssured.port = 443; }

Di sini, kami menetapkan URI dasar dan port untuk permintaan kami. Selain itu, kita juga dapat mengkonfigurasi jalur basis, pat root, dan otentikasi.

Catatan: kami juga dapat mengatur ulang ke standar standar REST-terjamin dengan menggunakan:

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 memvalidasi bahwa kode status adalah 200. Hanya jika gagal, permintaan dan respons akan dicatat.

12. Kesimpulan

Dalam tutorial ini, kami telah menjelajahi kerangka kerja yang dijamin REST dan melihat fitur-fitur terpentingnya yang dapat kami gunakan untuk menguji layanan RESTful kami dan memvalidasi tanggapan mereka.

Penerapan penuh dari semua contoh dan cuplikan kode ini dapat ditemukan di proyek GitHub yang dijamin REST.

Jackson bawah

Saya baru saja mengumumkan kursus Learn Spring baru , yang berfokus pada dasar-dasar Spring 5 dan Spring Boot 2:

>> LIHAT KURSUSnya