Menguji API REST dengan JBehave

1. Pengenalan

Dalam artikel ini, kita akan melihat JBehave dengan cepat, kemudian fokus untuk menguji API REST dari perspektif BDD.

2. JBehave dan BDD

JBehave adalah kerangka Pembangunan Berteraskan Tingkah Laku. Ini bertujuan untuk menyediakan cara yang intuitif dan mudah diakses untuk ujian penerimaan automatik.

Sekiranya anda tidak biasa dengan BDD, adalah idea yang baik untuk memulakan artikel ini, merangkumi kerangka ujian BDD lain - Timun, di mana kami memperkenalkan struktur dan ciri BDD umum.

Sama seperti kerangka kerja BDD yang lain, JBehave menggunakan konsep berikut:

  • Cerita - mewakili peningkatan fungsi perniagaan yang dapat dilaksanakan secara automatik, merangkumi satu atau beberapa senario
  • Senario - mewakili contoh konkrit tingkah laku sistem
  • Langkah - mewakili tingkah laku sebenar menggunakan kata kunci BDD klasik: Diberi , Bila dan Kemudian

Senario biasa ialah:

Given a precondition When an event occurs Then the outcome should be captured

Setiap langkah dalam senario sesuai dengan anotasi di JBehave:

  • @Diberikan : mulakan konteks
  • @Apabila : lakukan tindakan
  • @ Kemudian : uji hasil yang diharapkan

3. Ketergantungan Maven

Untuk memanfaatkan JBehave dalam projek maven kami, kebergantungan jbehave-core harus disertakan dalam pom :

 org.jbehave jbehave-core 4.1 test 

4. Contoh Pantas

Untuk menggunakan JBehave, kita perlu mengikuti langkah-langkah berikut:

  1. Tulis kisah pengguna
  2. Petakan langkah dari kisah pengguna ke kod Java
  3. Konfigurasikan cerita pengguna
  4. Jalankan ujian JBehave
  5. Hasil semakan

4.1. Cerita

Mari kita mulakan dengan kisah ringkas berikut: "sebagai pengguna, saya ingin menambah kaunter, sehingga saya dapat meningkatkan nilai kaunter sebanyak 1".

Kita boleh menentukan cerita dalam fail .story :

Scenario: when a user increases a counter, its value is increased by 1 Given a counter And the counter has any integral value When the user increases the counter Then the value of the counter must be 1 greater than previous value

4.2. Langkah Pemetaan

Dengan langkah-langkahnya, mari kita laksanakan ini di Jawa:

public class IncreaseSteps { private int counter; private int previousValue; @Given("a counter") public void aCounter() { } @Given("the counter has any integral value") public void counterHasAnyIntegralValue() { counter = new Random().nextInt(); previousValue = counter; } @When("the user increases the counter") public void increasesTheCounter() { counter++; } @Then("the value of the counter must be 1 greater than previous value") public void theValueOfTheCounterMustBe1Greater() { assertTrue(1 == counter - previousValue); } }

Ingat bahawa nilai dalam anotasi mestilah sesuai dengan keterangan .

4.3. Mengkonfigurasi Kisah Kita

Untuk melakukan langkah-langkahnya, kita perlu mengatur pentas untuk kisah kita:

public class IncreaseStoryLiveTest extends JUnitStories { @Override public Configuration configuration() { return new MostUsefulConfiguration() .useStoryLoader(new LoadFromClasspath(this.getClass())) .useStoryReporterBuilder(new StoryReporterBuilder() .withCodeLocation(codeLocationFromClass(this.getClass())) .withFormats(CONSOLE)); } @Override public InjectableStepsFactory stepsFactory() { return new InstanceStepsFactory(configuration(), new IncreaseSteps()); } @Override protected List storyPaths() { return Arrays.asList("increase.story"); } }

Dalam storyPaths () , kami menyediakan jalan fail .story kami untuk dihuraikan oleh JBehave. Pelaksanaan langkah sebenarnya disediakan dalam langkahFactory () . Kemudian dalam konfigurasi () , pemuat cerita dan laporan cerita dikonfigurasikan dengan betul.

Sekarang kita sudah siap, kita boleh memulakan cerita kita hanya dengan menjalankan: ujian bersih mvn .

4.4. Menyemak Keputusan Ujian

Kami dapat melihat keputusan ujian kami di konsol. Oleh kerana ujian kami berjaya, hasilnya akan sama dengan kisah kami:

Scenario: when a user increases a counter, its value is increased by 1 Given a counter And the counter has any integral value When the user increases the counter Then the value of the counter must be 1 greater than previous value

Sekiranya kita lupa untuk melaksanakan sebarang langkah senario, laporan akan memberi tahu kita. Katakanlah kita tidak melaksanakan langkah @When :

Scenario: when a user increases a counter, its value is increased by 1 Given a counter And the counter has any integral value When the user increases the counter (PENDING) Then the value of the counter must be 1 greater than previous value (NOT PERFORMED)
@When("the user increases the counter") @Pending public void whenTheUserIncreasesTheCounter() { // PENDING }

Laporan tersebut akan mengatakan bahawa @Apabila langkah belum selesai, dan kerana itu, langkah @ Kemudian tidak akan dilaksanakan.

Bagaimana jika langkah @Kami gagal? Kami dapat mengesan ralat dengan segera dari laporan:

Scenario: when a user increases a counter, its value is increased by 1 Given a counter And the counter has any integral value When the user increases the counter Then the value of the counter must be 1 greater than previous value (FAILED) (java.lang.AssertionError)

5. Menguji REST API

Sekarang kita telah memahami asas-asas JBhave ; kita akan melihat cara menguji API REST dengannya. Ujian kami akan berdasarkan artikel kami sebelumnya yang membincangkan cara menguji REST API dengan Java.

Dalam artikel itu, kami menguji GitHub REST API dan terutama memfokuskan pada kod respons HTTP, tajuk, dan muatan. Untuk kesederhanaan, kami dapat menulisnya menjadi tiga cerita yang berasingan.

5.1. Menguji Kod Status

Cerita itu:

Scenario: when a user checks a non-existent user on github, github would respond 'not found' Given github user profile api And a random non-existent username When I look for the random user via the api Then github respond: 404 not found When I look for eugenp1 via the api Then github respond: 404 not found When I look for eugenp2 via the api Then github respond: 404 not found

Langkah-langkahnya:

public class GithubUserNotFoundSteps { private String api; private String nonExistentUser; private int githubResponseCode; @Given("github user profile api") public void givenGithubUserProfileApi() { api = "//api.github.com/users/%s"; } @Given("a random non-existent username") public void givenANonexistentUsername() { nonExistentUser = randomAlphabetic(8); } @When("I look for the random user via the api") public void whenILookForTheUserViaTheApi() throws IOException { githubResponseCode = getGithubUserProfile(api, nonExistentUser) .getStatusLine() .getStatusCode(); } @When("I look for $user via the api") public void whenILookForSomeNonExistentUserViaTheApi( String user) throws IOException { githubResponseCode = getGithubUserProfile(api, user) .getStatusLine() .getStatusCode(); } @Then("github respond: 404 not found") public void thenGithubRespond404NotFound() { assertTrue(SC_NOT_FOUND == githubResponseCode); } //... }

Perhatikan bagaimana, dalam pelaksanaan langkah-langkah, kami menggunakan fitur suntikan parameter . Argumen yang diekstrak dari calon langkah hanya sesuai dengan urutan semula jadi dengan parameter dalam metode Java yang dijelaskan.

Juga, parameter bernama yang disokong disokong:

@When("I look for $username via the api") public void whenILookForSomeNonExistentUserViaTheApi( @Named("username") String user) throws IOException

5.2. Menguji Jenis Media

Inilah kisah pengujian jenis MIME ringkas:

Scenario: when a user checks a valid user's profile on github, github would respond json data Given github user profile api And a valid username When I look for the user via the api Then github respond data of type json

Berikut adalah langkah-langkahnya:

public class GithubUserResponseMediaTypeSteps { private String api; private String validUser; private String mediaType; @Given("github user profile api") public void givenGithubUserProfileApi() { api = "//api.github.com/users/%s"; } @Given("a valid username") public void givenAValidUsername() { validUser = "eugenp"; } @When("I look for the user via the api") public void whenILookForTheUserViaTheApi() throws IOException { mediaType = ContentType .getOrDefault(getGithubUserProfile(api, validUser).getEntity()) .getMimeType(); } @Then("github respond data of type json") public void thenGithubRespondDataOfTypeJson() { assertEquals("application/json", mediaType); } }

5.3. Menguji Beban JSON

Kemudian kisah terakhir:

Scenario: when a user checks a valid user's profile on github, github's response json should include a login payload with the same username Given github user profile api When I look for eugenp via the api Then github's response contains a 'login' payload same as eugenp

Dan pelaksanaan langkah lurus:

public class GithubUserResponsePayloadSteps { private String api; private GitHubUser resource; @Given("github user profile api") public void givenGithubUserProfileApi() { api = "//api.github.com/users/%s"; } @When("I look for $user via the api") public void whenILookForEugenpViaTheApi(String user) throws IOException { HttpResponse httpResponse = getGithubUserProfile(api, user); resource = RetrieveUtil.retrieveResourceFromResponse(httpResponse, GitHubUser.class); } @Then("github's response contains a 'login' payload same as $username") public void thenGithubsResponseContainsAloginPayloadSameAsEugenp(String username) { assertThat(username, Matchers.is(resource.getLogin())); } }

6. Ringkasan

Dalam artikel ini, kami telah memperkenalkan JBehave secara ringkas dan melaksanakan ujian REST API gaya BDD.

Jika dibandingkan dengan kod ujian Java biasa kami, kod yang dilaksanakan dengan JBehave kelihatan lebih jelas dan intuitif dan laporan hasil ujian kelihatan lebih elegan.

Seperti biasa, kod contoh boleh didapati di projek Github.