JAVA中單元測試的常用方式(小結(jié))
什么是單元測試
單元測試(英語:Unit Testing)又稱為模塊測試, 是針對程序模塊(軟件設(shè)計(jì)的最小單位)來進(jìn)行正確性檢驗(yàn)的測試工作。程序單元是應(yīng)用的最小可測試部件。在過程化編程中,一個單元就是單個程序、函數(shù)、過程等;對于面向?qū)ο缶幊?,最小單元就是方法,包括基類(超類)、抽象類、或者派生類(子類)中的方法?br />
通常來說,程序員每修改一次程序就會進(jìn)行最少一次單元測試,在編寫程序的過程中前后很可能要進(jìn)行多次單元測試,以證實(shí)程序達(dá)到軟件規(guī)格書要求的工作目標(biāo),沒有程序錯誤;雖然單元測試不是什么必須的,但也不壞,這牽涉到項(xiàng)目管理的政策決定。
單元測試的優(yōu)點(diǎn)
優(yōu)質(zhì)的單元測試可以保障開發(fā)質(zhì)量和程序的魯棒性。在大多數(shù)互聯(lián)網(wǎng)企業(yè)中開發(fā)工程師在研發(fā)過程中都會頻繁地執(zhí)行測試用例,運(yùn)行失敗的單測能幫助我們快速排查和定位問題 使問題在被帶到線上之前完成修復(fù)。正如軟件工程界的一條金科玉律----越早發(fā)現(xiàn)的缺陷,其修復(fù)成本越低。一流的測試能發(fā)現(xiàn)未發(fā)生的故障;二流的測試能快速定位故障的發(fā)生點(diǎn);三流的測試則疲于奔命,一直跟在故障后面進(jìn)行功能回歸。
JAVA中常用的單元測試工具
JUnit/JUnit5
junit是老牌測試框架了,也是目前引用最廣泛的一個框架。當(dāng)前已經(jīng)更新到Junit5,功能更強(qiáng)大。
class StandardTests { @BeforeAll static void initAll() { } @BeforeEach void init() { } @Test void succeedingTest() { } @Test void failingTest() { fail("a failing test"); } @Test @Disabled("for demonstration purposes") void skippedTest() { // not executed } @Test void abortedTest() { assumeTrue("abc".contains("Z")); fail("test should have been aborted"); } @AfterEach void tearDown() { } @AfterAll static void tearDownAll() { } }
assertj
https://assertj.github.io/doc/
一個功能強(qiáng)悍的斷言工具,支持各種斷言方式
// entry point for all assertThat methods and utility methods (e.g. entry) import static org.assertj.core.api.Assertions.*; // basic assertions assertThat(frodo.getName()).isEqualTo("Frodo"); assertThat(frodo).isNotEqualTo(sauron); // chaining string specific assertions assertThat(frodo.getName()).startsWith("Fro") .endsWith("do") .isEqualToIgnoringCase("frodo"); // collection specific assertions (there are plenty more) // in the examples below fellowshipOfTheRing is a List<TolkienCharacter> assertThat(fellowshipOfTheRing).hasSize(9) .contains(frodo, sam) .doesNotContain(sauron); // as() is used to describe the test and will be shown before the error message assertThat(frodo.getAge()).as("check %s's age", frodo.getName()).isEqualTo(33); // Java 8 exception assertion, standard style ... assertThatThrownBy(() -> { throw new Exception("boom!"); }).hasMessage("boom!"); // ... or BDD style Throwable thrown = catchThrowable(() -> { throw new Exception("boom!"); }); assertThat(thrown).hasMessageContaining("boom"); // using the 'extracting' feature to check fellowshipOfTheRing character's names (Java 7) assertThat(fellowshipOfTheRing).extracting("name") .contains("Boromir", "Gandalf", "Frodo", "Legolas") // same thing using a Java 8 method reference assertThat(fellowshipOfTheRing).extracting(TolkienCharacter::getName) .doesNotContain("Sauron", "Elrond"); // extracting multiple values at once grouped in tuples (Java 7) assertThat(fellowshipOfTheRing).extracting("name", "age", "race.name") .contains(tuple("Boromir", 37, "Man"), tuple("Sam", 38, "Hobbit"), tuple("Legolas", 1000, "Elf")); // filtering a collection before asserting in Java 7 ... assertThat(fellowshipOfTheRing).filteredOn("race", HOBBIT) .containsOnly(sam, frodo, pippin, merry); // ... or in Java 8 assertThat(fellowshipOfTheRing).filteredOn(character -> character.getName().contains("o")) .containsOnly(aragorn, frodo, legolas, boromir); // combining filtering and extraction (yes we can) assertThat(fellowshipOfTheRing).filteredOn(character -> character.getName().contains("o")) .containsOnly(aragorn, frodo, legolas, boromir) .extracting(character -> character.getRace().getName()) .contains("Hobbit", "Elf", "Man"); // and many more assertions: iterable, stream, array, map, dates (java 7 and 8), path, file, numbers, predicate, optional ...
Mockito
一個單元測試中的Mock工具,可以很靈活的創(chuàng)建對象,配合單元測試。
// You can mock concrete classes and interfaces TrainSeats seats = mock(TrainSeats.class); // stubbing appears before the actual execution when(seats.book(Seat.near(WINDOW).in(FIRST_CLASS))).thenReturn(BOOKED); // the following prints "BOOKED" System.out.println(seats.book(Seat.near(WINDOW).in(FIRST_CLASS))); // the following prints "null" because // .book(Seat.near(AISLE).in(FIRST_CLASS))) was not stubbed System.out.println(seats.book(Seat.near(AISLE).in(FIRST_CLASS))); // the following verification passes because // .book(Seat.near(WINDOW).in(FIRST_CLASS)) has been invoked verify(seats).book(Seat.near(WINDOW).in(FIRST_CLASS)); // the following verification fails because // .book(Seat.in(SECOND_CLASS)) has not been invoked verify(seats).book(Seat.in(SECOND_CLASS));
其他
對于業(yè)務(wù)代碼,有時單元測試并不方便,因?yàn)槊看螁映杀具^高。可以使用適當(dāng)?shù)膯卧獪y試方式,比如可以提供一個測試接口,利用IDE的熱部署功能實(shí)現(xiàn)不重啟及時修改代碼。
但是對于非業(yè)務(wù)性代碼,進(jìn)行單元測試時非常有必要的,可以更早的發(fā)現(xiàn)代碼中的問題,同時也可以檢驗(yàn)程序的解耦性。
良好的代碼設(shè)計(jì)在單元測試時會更方便,反之緊耦合的設(shè)計(jì)會給單元測試帶來很大的困擾。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Java中枚舉的實(shí)現(xiàn)與應(yīng)用詳解
這篇文章主要介紹了Java中枚舉的實(shí)現(xiàn)與應(yīng)用詳解,EnumTest中還有一個VALUES數(shù)組,里面存儲著所有的枚舉實(shí)例,調(diào)用values方法時返回VALUES數(shù)組的clone,需要的朋友可以參考下2023-12-12Installij IDEA install或clean項(xiàng)目的使用
這篇文章主要介紹了Installij IDEA install或clean項(xiàng)目的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-08-08Eclipse中實(shí)現(xiàn)JS代碼提示功能(圖文教程)
本文通過圖文并茂的形式給大家介紹了Eclipse中實(shí)現(xiàn)JS代碼提示功能,非常不錯,具有參考借鑒價值,需要的朋友參考下吧2017-11-11CMD運(yùn)行Intellij Idea編譯后的class文件操作
這篇文章主要介紹了CMD運(yùn)行Intellij Idea編譯后的class文件操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-02-02javaweb學(xué)習(xí)總結(jié)——使用JDBC處理MySQL大數(shù)據(jù)
本篇文章主要介紹了JDBC處理MySQL大數(shù)據(jù),有時是需要用程序把大文本或二進(jìn)制數(shù)據(jù)直接保存到數(shù)據(jù)庫中進(jìn)行儲存的,非常具有實(shí)用價值,需要的朋友可以參考下。2016-11-11深入詳解java高并發(fā)熱點(diǎn)數(shù)據(jù)更新
這篇文章主要為大家深入介紹了java高并發(fā)熱點(diǎn)數(shù)據(jù)更新詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-04-04SpringBoot yaml語法與數(shù)據(jù)讀取操作詳解
YAML 是 “YAML Ain’t Markup Language”(YAML 不是一種標(biāo)記語言)的遞歸縮寫。在開發(fā)的這種語言時,YAML 的意思其實(shí)是:“Yet Another Markup Language”(仍是一種標(biāo)記語言),本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-07-07