Java Mocking入门—使用Mockito
我們都會編寫單元測試程序,但我們當前所面臨的挑戰是被測單元可能依賴于其他組件。而對于單元測試配置其他組件,絕對是過枉矯正。相反,我們可以使用Mocks框架代替其他組件,繼續進行單元測試。
為了展現如何使用mock框架,我編寫一個數據訪問層(DAL),該類對應用提供了一套API 接口來訪問和修改數據庫中的數據。之后在不需要連接數據庫的情況下,對DAL類進行單元測試。數據庫可以是本地數據庫、遠程數據庫、文件系統或者任何可以儲存和檢索數據的地方。使用DAL類幫助我們 將數據映射操作從應用代碼中分離出來。
使用maven建立一個Java工程。
| 1 | mvn archetype:generate -DgroupId=info.sanaulla -DartifactId=MockitoDemo -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false |
以上操作建立了一個MockitoDemo文件夾,然后創建源文件和測試文件的整個目錄結構。
考慮下面這個示例模型類:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | packageinfo.sanaulla.models; importjava.util.List; /** * Model class for the book details. */ publicclass Book { ??privateString isbn; ??privateString title; ??privateList<String> authors; ??privateString publication; ??privateInteger yearOfPublication; ??privateInteger numberOfPages; ??privateString image; ??publicBook(String isbn, ??????????????String title, ??????????????List<String> authors, ??????????????String publication, ??????????????Integer yearOfPublication, ??????????????Integer numberOfPages, ??????????????String image){ ????this.isbn = isbn; ????this.title = title; ????this.authors = authors; ????this.publication = publication; ????this.yearOfPublication = yearOfPublication; ????this.numberOfPages = numberOfPages; ????this.image = image; ??} ??publicString getIsbn() { ????returnisbn; ??} ??publicString getTitle() { ????returntitle; ??} ??publicList<String> getAuthors() { ????returnauthors; ??} ??publicString getPublication() { ????returnpublication; ??} ??publicInteger getYearOfPublication() { ????returnyearOfPublication; ??} ??publicInteger getNumberOfPages() { ????returnnumberOfPages; ??} ??publicString getImage() { ????returnimage; ??} } |
操作Book模型類的DAL類:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | packageinfo.sanaulla.dal; importinfo.sanaulla.models.Book; importjava.util.ArrayList; importjava.util.Arrays; importjava.util.Collections; importjava.util.List; /** * API layer for persisting and retrieving the Book objects. */ publicclass BookDAL { ??privatestatic BookDAL bookDAL = newBookDAL(); ??publicList<Book> getAllBooks(){ ??????returnCollections.EMPTY_LIST; ??} ??publicBook getBook(String isbn){ ??????returnnull; ??} ??publicString addBook(Book book){ ??????returnbook.getIsbn(); ??} ??publicString updateBook(Book book){ ??????returnbook.getIsbn(); ??} ??publicstatic BookDAL getInstance(){ ??????returnbookDAL; ??} } |
當前DAL層以上沒有任何功能,我們將對這段代碼TDD進行單元測試。DAL層可能與ORM映射API或者數據庫API通訊,而我們不關心的這些API是如何設計的。
測試驅動DAL層
對單元測試和Java Mock有很多框架,對這個例子,我將選擇JUnit做單元測試,Mockito作為Java mock。我們會在Maven的pom.xml文件中更新依賴屬性。
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ???????xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 <a href="http://maven.apache.org/maven-v4_0_0.xsd">http://maven.apache.org/maven-v4_0_0.xsd"</a>> ??<modelVersion>4.0.0</modelVersion> ??<groupId>info.sanaulla</groupId> ??<artifactId>MockitoDemo</artifactId> ??<packaging>jar</packaging> ??<version>1.0-SNAPSHOT</version> ??<name>MockitoDemo</name> ??<url>http://maven.apache.org</url> ??<dependencies> ????<!-- Dependency for JUnit --> ????<dependency> ??????<groupId>junit</groupId> ??????<artifactId>junit</artifactId> ??????<version>4.10</version> ??????<scope>test</scope> ????</dependency> ????<!-- Dependency for Mockito --> ????<dependency> ??????<groupId>org.mockito</groupId> ??????<artifactId>mockito-all</artifactId> ??????<version>1.9.5</version> ??????<scope>test</scope> ????</dependency> ??</dependencies> </project> |
現在進行BookDAL類的單元測試。單元測試中,我們將注入mock數據到BookDAL類,因此我們可以不依賴數據源就可以完成API的測試。
最初我們有一個空的測試類:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | publicclass BookDALTest { ??publicvoid setUp() throwsException { ??} ??publicvoid testGetAllBooks() throwsException { ??} ??publicvoid testGetBook() throwsException { ??} ??publicvoid testAddBook() throwsException { ??} ??publicvoid testUpdateBook() throwsException { ??} } |
我們將使用下面的setUp()函數把BookDAL類注入mock對象,并設置mock對象數據:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | publicclass BookDALTest { ??privatestatic BookDAL mockedBookDAL; ??privatestatic Book book1; ??privatestatic Book book2; ??@BeforeClass ??publicstatic void setUp(){ ????//Create mock object of BookDAL ????mockedBookDAL = mock(BookDAL.class); ????//Create few instances of Book class. ????book1 = newBook("8131721019","Compilers Principles", ????????????Arrays.asList("D. Jeffrey Ulman","Ravi Sethi","Alfred V. Aho","Monica S. Lam"), ????????????"Pearson Education Singapore Pte Ltd",2008,1009,"BOOK_IMAGE"); ????book2 = newBook("9788183331630","Let Us C 13th Edition", ????????????Arrays.asList("Yashavant Kanetkar"),"BPB PUBLICATIONS",2012,675,"BOOK_IMAGE"); ????//Stubbing the methods of mocked BookDAL with mocked data. ????when(mockedBookDAL.getAllBooks()).thenReturn(Arrays.asList(book1, book2)); ????when(mockedBookDAL.getBook("8131721019")).thenReturn(book1); ????when(mockedBookDAL.addBook(book1)).thenReturn(book1.getIsbn()); ????when(mockedBookDAL.updateBook(book1)).thenReturn(book1.getIsbn()); ??} ??publicvoid testGetAllBooks() throwsException {} ??publicvoid testGetBook() throwsException {} ??publicvoid testAddBook() throwsException {} ??publicvoid testUpdateBook() throwsException {} } |
在上面的setUp()方法中,我做了:
1. 創建一個BookDAL的mock對象
| 1 | BookDAL mockedBookDAL = mock(BookDAL.class); |
2. 存根帶mock數據的BookDAL對象的API,這樣無論何時調用API都可以返回mock數據。
| 1 2 3 4 5 | //When getAllBooks() is invoked then return the given data and so on for the other methods. when(mockedBookDAL.getAllBooks()).thenReturn(Arrays.asList(book1, book2)); when(mockedBookDAL.getBook("8131721019")).thenReturn(book1); when(mockedBookDAL.addBook(book1)).thenReturn(book1.getIsbn()); when(mockedBookDAL.updateBook(book1)).thenReturn(book1.getIsbn()); |
填充剩余的測試方法:
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 | packageinfo.sanaulla.dal; importinfo.sanaulla.models.Book; importorg.junit.BeforeClass; importorg.junit.Test; importstatic org.junit.Assert.*; importstatic org.mockito.Mockito.mock; importstatic org.mockito.Mockito.when; importjava.util.Arrays; importjava.util.List; publicclass BookDALTest { ??privatestatic BookDAL mockedBookDAL; ??privatestatic Book book1; ??privatestatic Book book2; ??@BeforeClass ??publicstatic void setUp(){ ????mockedBookDAL = mock(BookDAL.class); ????book1 = newBook("8131721019","Compilers Principles", ????????????Arrays.asList("D. Jeffrey Ulman","Ravi Sethi","Alfred V. Aho","Monica S. Lam"), ????????????"Pearson Education Singapore Pte Ltd",2008,1009,"BOOK_IMAGE"); ????book2 = newBook("9788183331630","Let Us C 13th Edition", ????????????Arrays.asList("Yashavant Kanetkar"),"BPB PUBLICATIONS",2012,675,"BOOK_IMAGE"); ????when(mockedBookDAL.getAllBooks()).thenReturn(Arrays.asList(book1, book2)); ????when(mockedBookDAL.getBook("8131721019")).thenReturn(book1); ????when(mockedBookDAL.addBook(book1)).thenReturn(book1.getIsbn()); ????when(mockedBookDAL.updateBook(book1)).thenReturn(book1.getIsbn()); ??} ??@Test ??publicvoid testGetAllBooks() throwsException { ????List<Book> allBooks = mockedBookDAL.getAllBooks(); ????assertEquals(2, allBooks.size()); ????Book myBook = allBooks.get(0); ????assertEquals("8131721019", myBook.getIsbn()); ????assertEquals("Compilers Principles", myBook.getTitle()); ????assertEquals(4, myBook.getAuthors().size()); ????assertEquals((Integer)2008, myBook.getYearOfPublication()); ????assertEquals((Integer)1009, myBook.getNumberOfPages()); ????assertEquals("Pearson Education Singapore Pte Ltd", myBook.getPublication()); ????assertEquals("BOOK_IMAGE", myBook.getImage()); ??} ??@Test ??publicvoid testGetBook(){ ????String isbn = "8131721019"; ????Book myBook = mockedBookDAL.getBook(isbn); ????assertNotNull(myBook); ????assertEquals(isbn, myBook.getIsbn()); ????assertEquals("Compilers Principles", myBook.getTitle()); ????assertEquals(4, myBook.getAuthors().size()); ????assertEquals("Pearson Education Singapore Pte Ltd", myBook.getPublication()); ????assertEquals((Integer)2008, myBook.getYearOfPublication()); ????assertEquals((Integer)1009, myBook.getNumberOfPages()); ??} ??@Test ??publicvoid testAddBook(){ ????String isbn = mockedBookDAL.addBook(book1); ????assertNotNull(isbn); ????assertEquals(book1.getIsbn(), isbn); ??} ??@Test ??publicvoid testUpdateBook(){ ????String isbn = mockedBookDAL.updateBook(book1); ????assertNotNull(isbn); ????assertEquals(book1.getIsbn(), isbn); ??} } |
使用maven命令: mvn test進行測試。輸出如下:
| 1 2 3 4 5 6 7 8 9 10 11 | ------------------------------------------------------- ?T E S T S ------------------------------------------------------- Running info.sanaulla.AppTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.029 sec Running info.sanaulla.dal.BookDALTest Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.209 sec Results : Tests run: 5, Failures: 0, Errors: 0, Skipped: 0 |
至此,通過使用mock框架,在不用實際配置數據源的情況下,就可以測試DAL類。
原文鏈接:? dzone ?翻譯:? ImportNew.com? -? liken譯文鏈接:? http://www.importnew.com/10083.html
總結
以上是生活随笔為你收集整理的Java Mocking入门—使用Mockito的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Mockito:一个强大的用于Java开
- 下一篇: 说说初用 Mock 工具测试碰到的坑