学习了基本知识后,就可以实战了,Mockito的实际使用还是比较麻烦的。因为在实际使用中,最常遇到的就是需要模拟第三方类库的行为。
比如现在有一个类FTPFileTransfer,实现了向FTP传输文件的功能。这个类中使用了apache的ftp类org.apache.commons.net.ftp.FTPClient;现在测试FTPFileTransfer 这个类中的isFTPConnected方法, 希望模拟无法连接ftp的情况,测试是否记录了错误log。
public class FTPFileTransfer { //为了测试当ftp链接不上时,是否真的会记log,我们必须mock一个假的FTPClient对象,用该对象传递/覆盖掉真实的FTPClient对象ftp,并强制让这个假对象返回"无法连接",然后看是否会记log. private FTPClient ftp; private boolean isFTPConnected(){ if (!ftp.isConnected()) { logger.error("Disconnected from FTP."); } }
因此使用mock需要解决的问题是: 如何用mock的FTP对象覆盖掉真实代码中调用的FTPClient。因此需要将mock对象传递进去。
这里对源代码有一个限制:
源代码中必须使用set和get方法来设置/获得ftp对象,这样测试代码可以使用set来传递mock对象。或者测试代码中写一个方法覆盖掉源代码中实例化ftp对象的方法,且测试代码中使用mock ftp对象。
现假定源代码中使用了get/set,有如下方法进行单元测试:
一.创建一个返回FTPFileTransfer instance的方法
//使用mock()方法创建一个FTP的mock对象mockedFTP。 FTPClient mockedFTP = mock(FTPClient.class); //Stub “无法连接” when(mockedFTP.isConnected())).thenReturn("无法连接"); //写一个get方法返回FTPFileTransfer的实例用来测试,将mockedFTP作为参数传递进去。同时在这个方法内部用set方法将FTPFileTransfer类中的成员变量FTPClient ftp更改为mockFTP。 //这样我们就得到了一个FTPFileTransfer的实例,同时里面的ftp已经变成了我们希望的mockFTP。 private FTPFileTransfer getMockTaskFileTransfer(final FTPClientmockedFTP) { FTPFileTransfer test = new FTPFileTransfer("127.0.0.1", 8888, "//usr", "username", "password"); test.setFTPClient(mockedFTP); return test; } @Test public void testTransfer() throws SocketException, IOException{ FTPFileTransfer test = getMockTaskFileTransfer(); //得到这个实例以后,就直接调用这个实例的isFTPConnected方法,然后去log文件里找有没有我们希望的log就行了。注意此时,mockedFTP一定会返回"无法连接",所以isFTPConnected一定会记log。 test.isFTPConnected(); }
二.用subclass-and-override实现
从名字就可以看出,通过创建被测试类的子类,覆盖掉被测试类的getFTPClient()方法,将mock对象传递进去。
class MockFTPFileTransfer extends FTPFileTransfer{ public MockFTPFileTransfer(){ super("127.0.0.1", 8888, "//usr", "username", "password"); } //源代码中必须使用get来获得ftp对象,否则mock不会生效 @Override public FTPClient getFTPClient(){ FTPClient mockedFTP = mock(FTPClient.class); when(mockedFTP.isConnected()).thenReturn(true); return mockedFTP; } }
@Test public void testTransfer() throws SocketException, IOException{ FTPFileTransfer test = new MockFTPFileTransfer(); test.isFTPConnected(); }
三.用partial mock实现
partial mock是1.8之后的新功能。通常情况下会使用mock出来的对象完全覆盖掉被模拟的对象,对于那些没有stub的方法,则会返回build-in 类型的默认值。
@Test public void testTransfer() throws SocketException, IOException{ //模拟一个FTPClient对象,同时stub行为。 FTPClient mockedFTP = mock(FTPClient.class); when(mockedFTP.isConnected()).thenReturn(true); //spy可以模拟一个real object //这里的可以认为是spy在real object上包了一层,除了getFTPClient()被覆盖掉以外,其他方法仍然是真实对象的。 //这就是partial mock的概念: 仅仅用mock对象覆盖源对象的一部分,而不是全部。 FTPFileTransfer spyFTP= spy(new FTPFileTransfer("127.0.0.1", "//usr", "username", "password")); when(spyFTP.getFTPClient()).thenReturn(mockedFTP); spyFTP.setFTPClient(mockedFTP); spyFTP.isFTPConnected(); }
相关推荐
本篇文章将深入探讨 Mockito 和 JUnit 的集成使用,以及如何通过它们来提升 Java 应用的测试质量。 ### 1. JUnit 简介 JUnit 是一个开源的 Java 单元测试框架,它使得编写和运行测试用例变得简单。JUnit 提供了...
本篇将深入探讨这两者的应用,并结合具体实例进行详细解析。 一、TestNG简介 TestNG是由Cédric Beust创建的一个自动化测试框架,其设计理念是提供更丰富、更强大的测试能力,包括支持多种测试类型(如单元测试、...
本篇文章将深入探讨如何在Spring项目中集成TestNG和Mockito进行单元测试。 TestNG是一个强大的测试框架,它扩展了JUnit的功能,提供了更灵活的测试配置,如并发测试、更丰富的注解、更详尽的测试报告等。首先,你...
本篇文章将详细介绍这两个库的用途、使用方法以及一些实际案例。 Mockito是一款强大的Java模拟框架,它允许开发者在单元测试中创建和配置模拟对象,以隔离被测试代码并控制其行为。通过模拟,我们可以测试代码在...
本篇文章将深入探讨如何结合TestNG、Mockito以及Spring的自动装配注解进行有效的集成测试。以下是对这些技术的详细说明: TestNG是一个功能强大的测试框架,它是JUnit的替代品,提供了更丰富的功能,如并行测试执行...
本篇文章将深入解析如何使用 Mockito 实现 Java 单元测试。 首先,让我们看一个简单的例子,有一个名为 `ItemService` 的接口,它有一个方法 `getItemNameUpperCase`,该方法根据传入的 `itemId` 从 `...
本篇文章将深入探讨JUnit4的单元测试实例,帮助你更好地理解和应用这个工具。 一、JUnit4简介 JUnit4相较于之前的版本,引入了注解(Annotation)机制,极大地简化了测试用例的编写。例如,`@Test`注解用于标记测试...
本篇文章将深入探讨Spring Framework 4.2.5版本中的关键模块和功能,以帮助开发者更好地理解和应用这一强大的工具。 1. **Spring Core**:作为Spring框架的基础,`spring-core-4.2.5.RELEASE.jar`包含了IoC...
- **数组**:一维、二维数组的声明、初始化和使用。 - **字符串**:String类的特性和操作方法。 2. **进阶篇**: - **异常处理**:try-catch-finally语句,自定义异常。 - **集合框架**:List、Set、Map接口...
本篇将深入探讨一款基于Java实现的选修课程管理系统V1.2.3,通过对源码的解析,揭示其设计原理和实现细节。 首先,我们要明确的是,选修课程管理系统是一款针对高校学生与教师进行选课操作的信息化管理工具。它涵盖...
本篇将围绕Spring Framework 4.0.x版本进行深入探讨,带你了解这一版本的核心特性,源码剖析以及实际应用。 1. **核心模块介绍** Spring Framework 4.0.x主要由以下几个核心模块构成: - **Core Container**:...
本篇文章将详细阐述Android开发中的关键概念和技术,同时通过实例来加深理解。 1. **Android系统架构**:Android系统由Linux内核、硬件抽象层、运行库层、应用程序框架层和应用程序层组成。理解这五层架构对于开发...
本篇文章将深入探讨如何在SpringBoot项目中整合Hibernate,通过实例来展示其工作原理和实际应用。 一、SpringBoot简介 SpringBoot是由Pivotal团队提供的全新框架,其设计目标是简化新Spring应用的初始搭建以及开发...
本篇文章将深入探讨RoboGuice的源码,揭示其工作原理和使用技巧。 1. **依赖注入简介** 依赖注入的核心思想是对象之间的依赖关系不再由对象自身管理,而是由外部容器负责。这样可以降低对象间的耦合度,使代码更...
**步骤二:定义行为** ```java // 当调用userRepository.findById(1)时,返回一个预设的User对象 User user = new User(1, "John Doe"); Mockito.when(userRepository.findById(1)).thenReturn(user); ``` **步骤三...
本篇文章将详细探讨如何利用CXF框架开发一个Web服务客户端,以及如何进行测试。 一、CXF简介 CXF全称CXF CXF (Continued eXtensible Framework),它是一个Java框架,提供了创建和消费Web服务的能力。CXF支持WS-*...
本篇将基于"gradle-rest-server-spring-源码.rar"这一资源,深入探讨如何使用Gradle管理和构建一个基于Spring的RESTful服务,并解析其内部实现原理。 首先,Gradle是Java生态系统中的一个强大构建工具,它以Groovy...
这篇博文链接指向的资源包"android学习资料"可能包含了各种教程、代码示例和实用工具,对于初学者和进阶者都是宝贵的参考资料。以下是根据标题和标签推测的一些关键知识点及详细解释: 1. **源码分析**: - ...
本篇文章将聚焦于Spring Framework 4.0.0.RELEASE版本,探讨其主要特性、核心组件以及在实际开发中的应用。 首先,Spring Framework 4.0.0.RELEASE是一个重要的里程碑,它引入了许多新特性和改进,旨在提升性能、...