Menggunakan SpringJUnit4ClassRunner dengan Parameterized

1. Ikhtisar

Dalam tutorial ini, kita akan melihat cara membuat parameter pengujian integrasi Spring yang diterapkan di JUnit4 dengan runner pengujian JUnit berparameter .

2. SpringJUnit4ClassRunner

SpringJUnit4ClassRunner adalah implementasi ClassRunner JUnit4 yang menyematkan TestContextManager Spring ke dalam pengujian JUnit .

TestContextManager adalah titik masuk ke kerangka kerja Spring TestContext dan oleh karena itu mengelola akses ke Spring ApplicationContext dan injeksi ketergantungan di kelas pengujian JUnit. Jadi, SpringJUnit4ClassRunner memungkinkan pengembang untuk mengimplementasikan tes integrasi untuk komponen Spring seperti pengontrol dan repositori.

Misalnya, kami dapat mengimplementasikan pengujian integrasi untuk RestController kami :

@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration(classes = WebConfig.class) public class RoleControllerIntegrationTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; private static final String CONTENT_TYPE = "application/text;charset=ISO-8859-1"; @Before public void setup() throws Exception { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); } @Test public void givenEmployeeNameJohnWhenInvokeRoleThenReturnAdmin() throws Exception { this.mockMvc.perform(MockMvcRequestBuilders .get("/role/John")) .andDo(print()) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)) .andExpect(MockMvcResultMatchers.content().string("ADMIN")); } }

Seperti yang dapat dilihat dari pengujian, Kontroler kami menerima nama pengguna sebagai parameter jalur dan mengembalikan peran pengguna yang sesuai.

Sekarang, untuk menguji layanan REST ini dengan kombinasi nama pengguna / peran yang berbeda, kita harus mengimplementasikan tes baru:

@Test public void givenEmployeeNameDoeWhenInvokeRoleThenReturnEmployee() throws Exception { this.mockMvc.perform(MockMvcRequestBuilders .get("/role/Doe")) .andDo(print()) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)) .andExpect(MockMvcResultMatchers.content().string("EMPLOYEE")); }

Hal ini dapat dengan cepat lepas kendali untuk layanan yang memungkinkan sejumlah besar kombinasi input.

Untuk menghindari pengulangan semacam ini di kelas pengujian kami, mari kita lihat cara menggunakan Parameterized untuk mengimplementasikan pengujian JUnit yang menerima banyak input.

3. Menggunakan Parameterized

3.1. Menentukan Parameter

Parameterized adalah runner pengujian JUnit kustom yang memungkinkan kita menulis satu kasus pengujian dan menjalankannya pada beberapa parameter input:

@RunWith(Parameterized.class) @WebAppConfiguration @ContextConfiguration(classes = WebConfig.class) public class RoleControllerParameterizedIntegrationTest { @Parameter(value = 0) public String name; @Parameter(value = 1) public String role; @Parameters public static Collection data() { Collection params = new ArrayList(); params.add(new Object[]{"John", "ADMIN"}); params.add(new Object[]{"Doe", "EMPLOYEE"}); return params; } //... }

Seperti yang ditunjukkan di atas, kami menggunakan anotasi @Parameters untuk menyiapkan parameter input yang akan dimasukkan ke dalam pengujian JUnit. Kami juga menyediakan pemetaan nilai-nilai ini dalam nama dan peran bidang @Parameter .

Tapi sekarang, kami memiliki masalah lain untuk dipecahkan - JUnit tidak mengizinkan banyak pelari dalam satu kelas pengujian JUnit . Ini berarti kita tidak dapat memanfaatkan SpringJUnit4ClassRunner untuk menyematkan TestContextManager ke dalam kelas pengujian kita. Kita harus mencari cara lain untuk menyematkan TestContextManager .

Untungnya, Spring menyediakan beberapa opsi untuk mencapai ini. Kami akan membahas ini di bagian berikut.

3.2. Menginisialisasi TestContextManager Secara Manual

Opsi pertama cukup sederhana, karena Spring memungkinkan kita untuk menginisialisasi TestContextManager secara manual:

@RunWith(Parameterized.class) @WebAppConfiguration @ContextConfiguration(classes = WebConfig.class) public class RoleControllerParameterizedIntegrationTest { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; private TestContextManager testContextManager; @Before public void setup() throws Exception { this.testContextManager = new TestContextManager(getClass()); this.testContextManager.prepareTestInstance(this); this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); } //... }

Khususnya, dalam contoh ini, kami menggunakan runner Parameterized daripada SpringJUnit4ClassRunner. Selanjutnya, kami menginisialisasi TestContextManager dalam metode setup () .

Sekarang, kita dapat mengimplementasikan uji JUnit berparameter kita:

@Test public void givenEmployeeNameWhenInvokeRoleThenReturnRole() throws Exception { this.mockMvc.perform(MockMvcRequestBuilders .get("/role/" + name)) .andDo(print()) .andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.content().contentType(CONTENT_TYPE)) .andExpect(MockMvcResultMatchers.content().string(role)); }

JUnit akan menjalankan kasus uji ini dua kali - satu kali untuk setiap rangkaian input yang kami tentukan menggunakan anotasi @Parameters .

3.3. SpringClassRule dan SpringMethodRule

Umumnya, tidak disarankan untuk menginisialisasi TestContextManager secara manual . Sebagai gantinya, Spring merekomendasikan penggunaan SpringClassRule dan SpringMethodRule.

SpringClassRule mengimplementasikan TestRule JUnit - cara alternatif untuk menulis kasus pengujian. TestRule dapat digunakan untuk menggantikan operasi penyiapan dan pembersihan yang sebelumnya dilakukan dengan metode @Before, @BeforeClass, @After, dan @AfterClass .

SpringClassRule menyematkan fungsionalitas tingkat kelas TestContextManager di kelas pengujian JUnit. Ini menginisialisasi TestContextManager dan memanggil penyiapan dan pembersihan Spring TestContext. Oleh karena itu, ini menyediakan injeksi ketergantungan dan akses ke ApplicationContext .

Selain SpringClassRule , kita juga harus menggunakan SpringMethodRule . yang menyediakan fungsionalitas tingkat instance dan tingkat metode untuk TestContextManager.

SpringMethodRule bertanggung jawab atas persiapan metode pengujian. Ini juga memeriksa kasus uji yang ditandai untuk dilewati dan mencegahnya berjalan.

Mari kita lihat bagaimana menggunakan pendekatan ini di kelas pengujian kita:

@RunWith(Parameterized.class) @WebAppConfiguration @ContextConfiguration(classes = WebConfig.class) public class RoleControllerParameterizedClassRuleIntegrationTest { @ClassRule public static final SpringClassRule scr = new SpringClassRule(); @Rule public final SpringMethodRule smr = new SpringMethodRule(); @Before public void setup() throws Exception { this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); } //... }

4. Kesimpulan

Dalam artikel ini, kita membahas dua cara untuk mengimplementasikan pengujian integrasi Spring menggunakan runner pengujian berparameter, bukan SpringJUnit4ClassRunner . Kami melihat cara menginisialisasi TestContextManager secara manual, dan kami melihat contoh menggunakan SpringClassRule dengan SpringMethodRule , pendekatan yang direkomendasikan oleh Spring.

Meskipun kami hanya membahas runner berparameterisasi di artikel ini, kami sebenarnya dapat menggunakan salah satu pendekatan ini dengan runner JUnit mana pun untuk menulis pengujian integrasi Spring.

Seperti biasa, semua kode contoh tersedia di GitHub.