Java Mocking入门—使用Mockito

Java Mocking入门—使用Mockito

2014/03/10 | 分类: 基础技术 | 0 条评论 | 标签: 单元测试

分享到:8

本文由 ImportNew - liken 翻译自 dzone。欢迎加入翻译小组。转载请见文末要求。

我们都会编写单元测试程序,但我们当前所面临的挑战是被测单元可能依赖于其他组件。而对于单元测试配置其他组件,绝对是过枉矫正。相反,我们可以使用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.comliken
译文链接: http://www.importnew.com/10083.html
转载请保留原文出处、译者和译文链接。]

时间: 2024-11-05 17:25:11

Java Mocking入门—使用Mockito的相关文章

Java反射入门

Java这么多高灵活性,很多都是利用反射来实现的,所谓的反射是指,编译期间完全未知的classes,运行时,对任一个类(根据类名-字符串),能够知道这个类的所有属性和方法:对于任一个对象,都能够调用它的任意一个方法和属性. 简而言之,Java反射机制主要提供了以下功能: ?  在运行时判断任意一个对象所属的类:obj.getClass() ?  在运行时构造任意一个类的对象: ?  在运行时判断任意一个类所具有的成员变量和方法: ?  在运行时调用任意一个对象的方法. 下面我们先用一个简单小例体

《Java从入门到放弃》文章目录

转眼半个月过去了,不知不觉也写了10篇博客,突然发现所有的目录都没有纯列表的展示,所以特意写一个目录篇,来记录该系列下所有的文章. 当然,因为现在还没有写完,所以先按时间顺序排列,等相关内容都写完后,再按学习顺序来整理. <Java从入门到放弃>入门篇:XMLHttpRequest的基本用法 <Java从入门到放弃>入门篇:Struts2的基本访问方 <Java从入门到放弃>入门篇:Struts2的基本访问方式(二) <Java从入门到放弃>入门篇:Stru

Java基础入门 目录:

本系列博文内容主要是自己日常工作学习中常见.注意.以及还需要巩固的内容,有些本人熟练掌握的内容不在该博文内,也不能当作查询技术的"海词"使用,主要用于学习并记录成长!!! Java开发入门 Java编程基础 Java API

[java web 入门](一)MyEclipse &amp;amp; HelloWorld 记录

第一部,下载安装MyEclipse for mac. http://downloads.myeclipseide.com/downloads/products/eworkbench/2014/installers/myeclipse-spring-2014-GA-offline-installer-macosx.dmg   http://downloads.myeclipseide.com/downloads/products/eworkbench/2014/installers/myeclip

Java泛型入门

  Java泛型入门 在学习本章之前,须要对Java的集合(Collection.Map)有一定的基础. Java集合有一个缺点.就是把一个对象"丢进"集合里后,集合就会"忘记"这个对象的数据类型,当再次取出该对象时,该对象的编译类型就变成了Object类型(其执行时类型没变). 之所以这样设计是由于设计集合的程序猿不会知道我们要用它来保存什么类型的对象,所以这样设计具有非常好的通用性.可是这样做带来例如以下两个问题: l  集合对与元素类型没有限制,如一个集合

Java Web入门项目之“网络交友”的设计与实现

前言:这个小项目是我刚学习JSP时,参考"JSP程序设计"这本书写的.这里之所以说参考这本书而不是照着这本书写,主要是因为我自己完成的时候删掉了不少繁琐的写法(比如:文件上传):同时对书中容易产生SQL注入漏洞,XSS跨站脚本漏洞等地方的写法进行了修改过滤:登录页面加上了随机验证码.除此之外,还添加了文件管理功能 PS:整个项目没有特别的难点,可以分为一个个功能点实现,大神轻喷,个人认为对初学Java Web的童鞋还是有参考意义的 注:整个项目的完整源代码和sql文件我会在文末给出下载

Java Annotation入门

Java Annotation入门作者:cleverpig 版权声明:本文可以自由转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本声明作者:cleverpig(作者的Blog:http://blog.matrix.org.cn/page/cleverpig)原 文:[http://www.matrix.org.cn/resource/article/44/44048_Java+Annotation.html]http://www.matrix.org.cn/resource/arti

Java新手入门的30个基本概念

Java新手入门的30个基本概念 在我们学习Java的过程中,掌握其中的基本概念对我们的学习无论是J2SE,J2EE,J2ME都是很重要的,J2SE是Java的基础,所以有必要对其中的基本概念做以归纳,以便大家在以后的学习过程中更好的理解java的精髓,在此我总结了30条基本的概念. Java概述: 目前Java主要应用于中间件的开发(middleware)---处理客户机于服务器之间的通信技术,早期的实践证明,Java不适合pc应用程序的开发,其发展逐渐变成在开发手持设备,互联网信息站,及车载

java新手入门

java新手入门 Java总有它的千般好处使你选择它,但这些随便翻翻书或在网上逛一圈就能找到答案.在本文中,笔者把自己学习Java的一些切身体会和过程写出来,供Java培训初学者做个参考. 我在学习Java的过程中主要围绕以下几个方面来学习: 1.时刻提醒自己Java是一种OOP语言工具,而不仅仅是编码,只有这样才能总体把握和运用Java. 2.在学习的过程中,最好能够了解Java的底层机制,而不是仅仅停留在表层,不是抄书上的例子运行出结果就可以.要注意,即便对一个简单的例子也要有耐心去琢磨.调