Menyuntikkan Mockito Mocks ke Spring Beans

1. Ikhtisar

Pada artikel ini kami akan menunjukkan bagaimana menggunakan injeksi ketergantungan untuk memasukkan tiruan Mockito ke Spring Beans untuk pengujian unit.

Dalam aplikasi dunia nyata, di mana komponen sering kali bergantung pada pengaksesan sistem eksternal, penting untuk menyediakan isolasi pengujian yang tepat sehingga kami dapat fokus pada pengujian fungsionalitas unit tertentu tanpa harus melibatkan seluruh hierarki kelas untuk setiap pengujian.

Menyuntikkan tiruan adalah cara yang bersih untuk memperkenalkan isolasi semacam itu.

2. Ketergantungan Maven

Kami membutuhkan dependensi Maven berikut untuk pengujian unit dan objek tiruan:

 org.springframework.boot spring-boot-starter 2.2.2.RELEASE   org.springframework.boot spring-boot-starter-test 2.2.2.RELEASE test   org.mockito mockito-core 2.21.0 

Kami memutuskan untuk menggunakan Spring Boot untuk contoh ini, tetapi Spring klasik juga akan berfungsi dengan baik.

3. Menulis Tes

3.1. Logika Bisnis

Pertama, mari buat layanan sederhana yang akan kami uji:

@Service public class NameService { public String getUserName(String id) { return "Real user name"; } }

Dan masukkan ke dalam kelas UserService :

@Service public class UserService { private NameService nameService; @Autowired public UserService(NameService nameService) { this.nameService = nameService; } public String getUserName(String id) { return nameService.getUserName(id); } }

Untuk tutorial ini, kelas yang diberikan mengembalikan satu nama terlepas dari id yang diberikan. Ini dilakukan agar kami tidak terganggu dengan menguji logika kompleks apa pun.

Kami juga membutuhkan kelas utama Spring Boot standar untuk memindai kacang dan menginisialisasi aplikasi:

@SpringBootApplication public class MocksApplication { public static void main(String[] args) { SpringApplication.run(MocksApplication.class, args); } }

3.2. Tes

Sekarang mari beralih ke logika uji. Pertama-tama, kita harus mengkonfigurasi konteks aplikasi untuk pengujian:

@Profile("test") @Configuration public class NameServiceTestConfiguration { @Bean @Primary public NameService nameService() { return Mockito.mock(NameService.class); } }

The @Profile penjelasan mengatakan musim semi untuk menerapkan konfigurasi ini hanya ketika “test” profil aktif. The @Primary penjelasan yang ada untuk memastikan hal ini digunakan sebagai pengganti yang nyata untuk autowiring. Metode itu sendiri membuat dan mengembalikan tiruan Mockito dari kelas NameService kami .

Sekarang kita bisa menulis tes unit:

@ActiveProfiles("test") @RunWith(SpringJUnit4ClassRunner.class) @SpringApplicationConfiguration(classes = MocksApplication.class) public class UserServiceUnitTest { @Autowired private UserService userService; @Autowired private NameService nameService; @Test public void whenUserIdIsProvided_thenRetrievedNameIsCorrect() { Mockito.when(nameService.getUserName("SomeId")).thenReturn("Mock user name"); String testName = userService.getUserName("SomeId"); Assert.assertEquals("Mock user name", testName); } }

Kami menggunakan anotasi @ActiveProfiles untuk mengaktifkan profil "tes" dan mengaktifkan konfigurasi tiruan yang kami tulis sebelumnya. Karena itu, Spring melakukan autowires instance nyata dari kelas UserService , tetapi tiruan kelas NameService . Tes itu sendiri adalah tes JUnit + Mockito yang cukup umum. Kami mengonfigurasi perilaku tiruan yang diinginkan, lalu memanggil metode yang ingin kami uji dan menegaskan bahwa metode tersebut mengembalikan nilai yang kami harapkan.

Mungkin juga (meskipun tidak disarankan) untuk menghindari penggunaan profil lingkungan dalam pengujian semacam itu. Untuk melakukannya, hapus anotasi @Profile dan @ActiveProfiles dan tambahkan anotasi @ContextConfiguration (class = NameServiceTestConfiguration.class) ke kelas UserServiceTest .

4. Kesimpulan

Dalam tutorial singkat ini, kami menunjukkan betapa mudahnya menyuntikkan Mockito ke dalam Spring Beans.

Seperti biasa, semua contoh kode tersedia di GitHub.