Saya mencoba menulis Tes Unit untuk kacang sederhana yang digunakan dalam program saya untuk memvalidasi formulir. Kacang tersebut dijelaskan dengan @Component
dan memiliki variabel kelas yang diinisialisasi menggunakan
@Value("${this.property.value}") private String thisProperty;
Saya ingin menulis unit test untuk metode validasi di dalam kelas ini, namun, jika mungkin saya ingin melakukannya tanpa menggunakan file properti. Alasan saya di balik ini, adalah bahwa jika nilai yang saya tarik dari file properti berubah, saya ingin itu tidak mempengaruhi kasus pengujian saya. Kasing uji saya menguji kode yang memvalidasi nilai, bukan nilai itu sendiri.
Apakah ada cara untuk menggunakan kode Java di dalam kelas pengujian saya untuk menginisialisasi kelas Java dan mengisi properti Spring @Value di dalam kelas itu kemudian menggunakannya untuk mengujinya?
Saya memang menemukan Cara ini yang tampaknya dekat, tetapi masih menggunakan file properti. Saya lebih suka semuanya menjadi kode Java.
Jawaban:
Jika mungkin saya akan mencoba menulis tes tersebut tanpa Konteks Musim Semi. Jika Anda membuat kelas ini dalam pengujian Anda tanpa pegas, maka Anda memiliki kontrol penuh atas bidangnya.
Untuk mengatur
@value
bidang Anda dapat menggunakan Mata AirReflectionTestUtils
- ia memiliki metodesetField
untuk mengatur bidang pribadi.@lihat JavaDoc : ReflectionTestUtils.setField (java.lang.Object, java.lang.String, java.lang.Object)
sumber
org.springframework.test.util.ReflectionTestUtils.setField(classUnderTest, "field", "value");
@Value
anotasi ke parameter konstruktor. Ini membuat kode uji lebih sederhana saat menulis kode secara manual, dan Spring Boot tidak peduli.Sejak Spring 4.1 Anda bisa mengatur nilai properti hanya dalam kode dengan menggunakan
org.springframework.test.context.TestPropertySource
anotasi pada tingkat kelas Tes Unit. Anda bisa menggunakan pendekatan ini bahkan untuk menyuntikkan properti ke instance kacang dependenSebagai contoh
Catatan: Ini perlu untuk memiliki instance
org.springframework.context.support.PropertySourcesPlaceholderConfigurer
dalam konteks SpringSunting 24-08-2017: Jika Anda menggunakan SpringBoot 1.4.0 dan yang lebih baru, Anda dapat menginisialisasi pengujian
@SpringBootTest
dan@SpringBootConfiguration
anotasi. Info lebih lanjut di siniDalam hal SpringBoot kami memiliki kode berikut
sumber
Jangan menyalahgunakan bidang pribadi dapatkan / ditetapkan oleh refleksi
Menggunakan refleksi seperti yang dilakukan dalam beberapa jawaban di sini adalah sesuatu yang bisa kita hindari.
Ini membawa nilai kecil di sini sementara itu menyajikan beberapa kelemahan:
@Value String field
. Besok Anda dapat mendeklarasikan5
atau10
tentang mereka di kelas itu dan Anda bahkan mungkin tidak langsung sadar bahwa Anda mengurangi desain kelas tersebut. Dengan pendekatan yang lebih terlihat untuk mengatur bidang-bidang ini (seperti konstruktor), Anda akan berpikir dua kali sebelum menambahkan semua bidang ini dan Anda mungkin akan merangkumnya ke dalam kelas lain dan digunakan@ConfigurationProperties
.Jadikan kelas Anda dapat diuji baik secara kesatuan maupun dalam integrasi
Untuk dapat menulis kedua tes unit biasa (yang tanpa wadah pegas berjalan) dan tes integrasi untuk kelas komponen Pegas Anda, Anda harus membuat kelas ini dapat digunakan dengan atau tanpa Pegas.
Menjalankan wadah dalam unit test ketika tidak diperlukan adalah praktik buruk yang memperlambat pembangunan lokal: Anda tidak menginginkannya.
Saya menambahkan jawaban ini karena sepertinya tidak ada jawaban di sini yang menunjukkan perbedaan ini dan karena itu mereka mengandalkan wadah yang berjalan secara sistematis.
Jadi saya pikir Anda harus memindahkan properti ini didefinisikan sebagai internal kelas:
ke dalam parameter konstruktor yang akan disuntikkan oleh Spring:
Contoh uji unit
Anda dapat instantiate
Foo
tanpa Spring dan menyuntikkan nilai apa pun untukproperty
terima kasih kepada konstruktor:Contoh uji integrasi
Anda dapat menyuntikkan properti dalam konteks dengan Spring Boot dengan cara sederhana ini berkat
properties
atribut@SpringBootTest
:Anda dapat menggunakan sebagai alternatif
@TestPropertySource
tetapi menambahkan anotasi tambahan:Dengan Spring (tanpa Spring Boot), itu seharusnya menjadi sedikit lebih rumit tetapi karena saya tidak menggunakan Spring tanpa Spring Boot sejak lama, saya tidak suka mengatakan hal yang bodoh.
Sebagai catatan: jika Anda memiliki banyak
@Value
bidang untuk diset, mengekstraknya ke dalam kelas yang diberi penjelasan@ConfigurationProperties
lebih relevan karena kami tidak ingin konstruktor dengan terlalu banyak argumen.sumber
final
, yaituprivate String final property
Jika mau, Anda masih dapat menjalankan tes dalam Konteks Musim Semi dan mengatur properti yang diperlukan di dalam kelas konfigurasi Spring. Jika Anda menggunakan JUnit, gunakan SpringJUnit4ClassRunner dan tentukan kelas konfigurasi khusus untuk pengujian Anda seperti itu:
Kelas yang diuji:
Kelas tes:
Dan kelas konfigurasi untuk tes ini:
Karena itu, saya tidak akan merekomendasikan pendekatan ini, saya hanya menambahkannya di sini untuk referensi. Menurut saya cara yang jauh lebih baik adalah menggunakan pelari Mockito. Dalam hal ini Anda tidak menjalankan tes di dalam Spring sama sekali, yang jauh lebih jelas dan sederhana.
sumber
Ini sepertinya berhasil, meskipun masih sedikit bertele-tele (saya masih menginginkan sesuatu yang lebih pendek):
sumber
@TestProperty
anotasi.@Value
, terlepas dari apakah properti yang bersangkutan telah diatur atau tidak.Menambahkan PropertyPlaceholderConfigurer dalam konfigurasi berfungsi untuk saya.
Dan di kelas tes
sumber