zoukankan      html  css  js  c++  java
  • Java Mocking入门—使用Mockito

    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
    package info.sanaulla.models;
     
    import java.util.List;
     
    /**
    * Model class for the book details.
    */
    public class Book {
     
      private String isbn;
      private String title;
      private List<String> authors;
      private String publication;
      private Integer yearOfPublication;
      private Integer numberOfPages;
      private String image;
     
      public Book(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;
     
      }
     
      public String getIsbn() {
        return isbn;
      }
     
      public String getTitle() {
        return title;
      }
     
      public List<String> getAuthors() {
        return authors;
      }
     
      public String getPublication() {
        return publication;
      }
     
      public Integer getYearOfPublication() {
        return yearOfPublication;
      }
     
      public Integer getNumberOfPages() {
        return numberOfPages;
      }
     
      public String getImage() {
        return image;
      }
    }

    操作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
    package info.sanaulla.dal;
     
    import info.sanaulla.models.Book;
     
    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.Collections;
    import java.util.List;
     
    /**
    * API layer for persisting and retrieving the Book objects.
    */
    public class BookDAL {
     
      private static BookDAL bookDAL = new BookDAL();
     
      public List<Book> getAllBooks(){
          return Collections.EMPTY_LIST;
      }
     
      public Book getBook(String isbn){
          return null;
      }
     
      public String addBook(Book book){
          return book.getIsbn();
      }
     
      public String updateBook(Book book){
          return book.getIsbn();
      }
     
      public static BookDAL getInstance(){
          return bookDAL;
      }
    }

    当前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
    <project xmlns="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
    public class BookDALTest {
      public void setUp() throws Exception {
     
      }
     
      public void testGetAllBooks() throws Exception {
     
      }
     
      public void testGetBook() throws Exception {
     
      }
     
      public void testAddBook() throws Exception {
     
      }
     
      public void testUpdateBook() throws Exception {
     
      }
    }

    我们将使用下面的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
    public class BookDALTest {
     
      private static BookDAL mockedBookDAL;
      private static Book book1;
      private static Book book2;
     
      @BeforeClass
      public static void setUp(){
        //Create mock object of BookDAL
        mockedBookDAL = mock(BookDAL.class);
     
        //Create few instances of Book class.
        book1 = new Book("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 = new Book("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());
      }
     
      public void testGetAllBooks() throws Exception {}
     
      public void testGetBook() throws Exception {}
     
      public void testAddBook() throws Exception {}
     
      public void testUpdateBook() throws Exception {}
    }

    在上面的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
    package info.sanaulla.dal;
     
    import info.sanaulla.models.Book;
    import org.junit.BeforeClass;
    import org.junit.Test;
     
    import static org.junit.Assert.*;
    import static org.mockito.Mockito.mock;
    import static org.mockito.Mockito.when;
     
    import java.util.Arrays;
    import java.util.List;
     
    public class BookDALTest {
     
      private static BookDAL mockedBookDAL;
      private static Book book1;
      private static Book book2;
     
      @BeforeClass
      public static void setUp(){
        mockedBookDAL = mock(BookDAL.class);
        book1 = new Book("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 = new Book("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
      public void testGetAllBooks() throws Exception {
     
        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
      public void 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
      public void testAddBook(){
        String isbn = mockedBookDAL.addBook(book1);
        assertNotNull(isbn);
        assertEquals(book1.getIsbn(), isbn);
      }
     
      @Test
      public void 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
    转载请保留原文出处、译者和译文链接。]
  • 相关阅读:
    HDU 1009 FatMouse' Trade
    HDU 2602 (简单的01背包) Bone Collector
    LA 3902 Network
    HDU 4513 吉哥系列故事——完美队形II
    LA 4794 Sharing Chocolate
    POJ (Manacher) Palindrome
    HDU 3294 (Manacher) Girls' research
    HDU 3068 (Manacher) 最长回文
    Tyvj 1085 派对
    Tyvj 1030 乳草的入侵
  • 原文地址:https://www.cnblogs.com/developer-ios/p/5382052.html
Copyright © 2011-2022 走看看