Kata pengantar
Artikel ini memperkenalkan cara menggunakan springboot+junit+mockito untuk pengujian unit, dan memilih kelas yang cocok dengan transaksi untuk melakukan pengujian unit.
Pahami persyaratan sebelum pengujian unit
Untuk menulis tes tunggal yang bagus, Anda harus terlebih dahulu memahami persyaratannya. Hanya dengan mengetahui apa yang harus Anda lakukan, Anda dapat mengetahui cara menguji. Tetapi artikel ini terutama berbicara tentang penggunaan mockito, dan tidak perlu memperhatikan kebutuhan spesifik. Oleh karena itu, bagian ini menghilangkan deskripsi persyaratan spesifik.
Mengisolasi dependensi eksternal
Case1. Cara Mengontrol Nilai Pengembalian Objek Ketergantungan Dianotasi oleh @Autowired atau @resource Anotasi di kelas yang diuji
Mengambil Pencocokan (Pencocokan Pesan Pencocokan, Pencocokan Sellorder) dari metode di bawah pencocokan uji yang serviceImpl.java sebagai contoh
Tes Class MatchingserviceImpl
Public Class MatchingServiceImpl mengimplementasikan pencocokan service {private static final logger log = loggerFactory.getLogger (matchingserviceImpl.class); @Autowired Private Quoteservice Quoteservice; ... pencocokan PublicResult Public (pencocokan Buyorder, Pencocokan Sellorder Pencocokan) {int CurrentPrice = Quoteservice.getCurrentPriceByProduct (buyorder.getProductCode ()); Hasil pencocokan result = pencocokan baru (); if (sellorder! = null && buyOrder! = null && jualDerOrder.getPrice () <= buyorder.getPrice ()) {...}}quoteservice.getCurrentPriceByProduct (buyorder.getProductCode ()); Untuk mengakses Redis untuk mendapatkan penawaran saat ini, kita perlu mengejek kutipan ketergantungan eksternal untuk mengontrol nilai pengembalian metode GetCurrentPriceByProduct. Anda dapat melakukannya menggunakan mockito, sebagai berikut:
Test Class MatchingserviceImpltest
Public ClassCerServiceImplTest memperluas mockitobasedtest { / *** objek yang ditandai oleh @mock akan secara otomatis disuntikkan ke dalam objek yang ditandai oleh @injectmocks* / @mock private quoteservice quoteservice; /** * <pr Pre> * objek yang akan diuji, ditandai dengan @InjectMocks, objek -objek yang ditandai oleh @Mock akan secara otomatis disuntikkan ke dalamnya. * Poin lain dari catatan adalah bahwa MatchingserviceImpl langsung baru (tidak apa -apa jika bukan hal baru setelah mockito 1.9), daripada disuntikkan melalui wadah pegas. Karena di sini saya tidak perlu mendapatkan ketergantungan lain dari wadah musim semi *, dan saya tidak perlu database, redis, zookeeper, mq, dan tidak ada yang tergantung padanya, jadi saya langsung baru *</per> */ @InjectMocks Private MatchingserviceImpl Matchingservice = new MatchingServiceImpl (); @Test public void testMatching_successwhencurrentpriceBetweenBuyPiceEndSellPrice () {pencocokan BuyOrder = new matchingOrder (); buyorder.setPrice (1000); buyorder.setCount (23); Pencocokan Pesan Sellorder = New MatchingOrder (); Sellorder.setPrice (800); Sellorder.setCount (20); // Metode Stubbing (metode stubbing) // Ketika (x) .thenreturn (y): Mengembalikan nilai yang ditentukan ketika metode yang ditentukan disebut mockito. MatchingResult Hasil = MatchingService.matching (Buyorder, Sellorder); org.junit.assert.asserTequals (true, result.issuccess ()); // menegaskan apakah perjodohan itu berhasil org.junit.assert.assertequals (20, result.getTradecount ()); // menegaskan kuantitas transaksi org.junit.assert.assertequals (900, hasil. Hasil. // menegaskan apakah kutipan terbaru memenuhi harapan}Kasus2. Ketika fungsi A diuji, bagaimana mengontrol nilai pengembalian fungsi B di kelas yang diuji?
Misalnya, ada fungsi startBuyProcess di MatchingserviceImpl, yang memanggil fungsi lain di kelas, seperti Gettopsellorder dan pencocokan. Bagaimana cara mengontrol nilai pengembalian dari dua fungsi ini?
Masalah yang harus diselesaikan di sini sebenarnya adalah bagaimana benar -benar menjalankan metode yang diukur (seperti startBuyProcess) dari kelas "tiruan parsial" kelas yang diuji, sedangkan metode lain (seperti Gettopsellorder) ditumpuk (tidak benar -benar masuk dan dieksekusi).
Tes Class MatchingserviceImpl
void startBuyProcess yang dilindungi (pencocokan buyorder, Boolean WaitFormatching) {while (true) {// Harga terbaik dari counterparty matchingorder topsellorder = gettopsellOrder (buyorder.getProductCode ()); MatchingResult MatchingResult = pencocokan (Buyorder, Topsellorder); if (matchingResult.issuccess ()) {doMatchingsuccess (buyorder, topsellorder, matchingResult, matchingType.buy); if (buyorder.getCount () <= 0) {break; }} else {if (waitFormatching) {// Tambahkan untuk mencocokkan antrian yang akan dicocokkan addToMatchingBuy (buyorder); } else {// mencabut pesanan sendCanclemsg (buyorder); } merusak; }}}}Menggunakan mockito.spy () dapat mencapai "tiruan parsial"
Test Class MatchingserviceImplTest.TestStartBuyProcess_incaseofmatchingsuccess
/** * * Uji apakah pemrosesan metode startBuyProcess setelah perjodohan yang berhasil memenuhi ekspektasi, yaitu, uji perilaku setelah memasuki cabang penilaian berikut * {@link matchingserviceImpl#startBuyProcess (pencocokan, boolean)} * <pre> * if (pencocokan result. MatchingResult, MatchingType.buy); * * if (buyorder.getCount () <= 0) { * break; *} *} * </pr Pre> * */ @test public void testStartBUyProcess_incaseOfMatchingSuccess () {pencocokan BuyOrder = new matchingOrder (); buyorder.setPrice (700); buyorder.setCount (23); // Gunakan mockito.spy () untuk menukis sebagian matchingservice matchingservice = mockito.spy (matchingservice); MatchingResult FirstMatchingResult = new matchingResult (); FirstMatchingResult.Setsuccess (true); FirstMatchingResult.SetTradecount (20); MatchingResult SecondMatchingResult = new matchingResult (); SecondMatchingResult.Setsuccess (false); // Doreturn (x) .Ketika (OBJ) .method () Setelah menumpuk metode, setelah menumpuk metode, program akan mengembalikan nilai yang ditentukan seperti yang diharapkan ketika menjalankan metode ini. Metode yang tidak ditumpuk akan dieksekusi akan dieksekusi secara real time. // Dua Doreturns berarti bahwa FirstMatchingResult dikembalikan ketika Matchingservice.matching disebut terlebih dahulu, dan SecondMatchingResult dikembalikan ketika panggilan kedua disebut // karena ada beberapa waktu loop di StartBuyProcess, metode pencocokan dapat dieksekusi beberapa kali beberapa kali Mockito.doreturn (firstmatchingResult) .doreturn (SecondMatchingResult) .Ketika (Matchingservice) .Matching (Mockito.Any (Matchingorder.class), Mockito.Any (Matchingorder.class)); Pencocokan Pesan Sellorder = New MatchingOrder (); Sellorder.setPrice (600); Sellorder.setCount (20); // menumpuk metode gettopsellorder mockito.doreturn (sellorder) .Ketika (matchingservice) .gettopsellorder (mockito.antstring ()); // menumpuk metode eksternal yang tergantung pada jedis mockito. // StartBuyProcess adalah fungsi yang sedang diuji. Jika Anda tidak menumpuk, Matchingservice.StartBuyProcess (Buyorder, True); // Pernyataan checksum berikutnya adalah untuk menguji perilaku metode doMatchingsuccess, yang juga merupakan tujuan dari tes ini.// Verifikasi dapat digunakan untuk memverifikasi berapa kali metode kelas tertentu telah dieksekusi? Berikut ini untuk memeriksa apakah jedisclient.zremfirst telah dieksekusi setelah mockito.verify (jedisclient, mockito.times (1)). Zremfirst (mockito.anystring ()); org.junit.assert.assertequals (3, buyorder.getCount ()); org.junit.assert.assertequals (0, sellorder.getCount ()); } Penggunaan mata -mata telah ditunjukkan. Mari kita bicara tentang "granularitas" tes unit dari testStartBuyPress_incaseofmatchingSuccess.
Tujuan testStartBuyProcess_incaseOfMatchingSuccess adalah untuk menguji domatchingsuccess. Kami telah bekerja sangat keras untuk menyelesaikan persiapan sebelumnya sebelum kami dapat menguji domatchingsuccess.
Praktik yang lebih baik adalah memulai metode pengujian baru untuk menguji domatchingsuccess secara terpisah, dan fokusnya juga terkonsentrasi. Setelah domatchingsuccess ditimpa, StartBuyProcess sebenarnya hanya dapat mencakup cabang penilaiannya sendiri. Cakupan masih tercapai, dan kode uji lebih mudah dipelihara. TestStartBUyProcess_incaseOfMatchingSuccess mudah dipengaruhi oleh perubahan karena terlalu banyak tanggung jawab yang dipertimbangkan. Perubahan hal -hal kecil dapat memengaruhi fungsi normalnya.
Memperkenalkan Kerangka Tes Ketergantungan Maven
<dependency> <GroupId> JUnit </GroupId> <ArTifactId> junit </artifactid> <version> 4.11 </version> <scope> test </seupop> </dependency> <dependency> <groupid> org.mockito </groupid> <ArTifactid> mockito-all </artifactid> </groupid> <Artifactid> mockito-semua </artifactid> </versi> </version.110. <scope> tes </seupop> </dependency> <dependency> <GroupId> org.springframework </groupid> <ArTifactId> tes pegas </t Artifactid> <version> 4.2.5.release </versi> <scope> tes </scope> </dependency>
Konstruksi Konteks Springboot+Junit+Mockito
Mockitobasedtest
@Runwith (springjunit4classrunner.class) @springapplicationConfiguration (class = testApplication.class) Public Abstract Class MockitoBasedTest {@Before public void setup () Lempar {// Inisialisasi semua objek mock yang dianotasi oleh mockito annotasi tes (// inisialisasi cangkir tes. }} // kelas tes lainnya mewarisi mockitobasedtest Di atas adalah semua konten artikel ini. Saya berharap ini akan membantu untuk pembelajaran semua orang dan saya harap semua orang akan lebih mendukung wulin.com.