文档章节

Mockito(二)--实例篇

chace0120
 chace0120
发布于 2014/04/01 09:59
字数 1149
阅读 739
收藏 1
点赞 0
评论 0

学习了基本知识后,就可以实战了。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();
    }

 

完毕!

大家都明白了吗?如果没有明白可以回帖,我会回答的。

------------------------------------------------------------------------------------------------------------------------------------

应要求发一个完整的UT


import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;

import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPConnection;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;
import javax.xml.transform.stream.StreamSource;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentMatcher;

import static org.junit.Assert.*;
import org.apache.commons.io.FileUtils;


import static org.mockito.Matchers.argThat;
import static org.mockito.Mockito.*;


public class ASAPSoapMessageTest {
    
    ASAPSoapMessage testASAPSoapMessage= new ASAPSoapMessage();
    String testSOAPRequest = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema\"><LoginRequest xmlns=\"http://asap.schemas.tfn.thomsonreuters.com/Messages/Base/2010-03-01/\"/></s:Body></s:Envelope>";
    File testFile = new File("testFile.xml");
    String testSOAPAction = "http://fackSOAPAction/";
    String testWebService = "http://fackWebService/";
    String testReply = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"><s:Body><LoginResponse xmlns=\"http://asap.schemas.tfn.thomsonreuters.com/Messages/Base/2010-03-01/\"/></s:Body></s:Envelope>";
    MessageFactory mf;
    SOAPMessage SOAPRequestTest;
    SOAPMessage replySOAPRequestTest;
    
    @Before 
    public void testUp() throws SOAPException{
        mf = MessageFactory.newInstance();
        SOAPRequestTest = mf.createMessage();
        replySOAPRequestTest = mf.createMessage();
    }
    
    @Test
    public void testGetSoapContent() throws IOException, SOAPException{
        
        String soapContentString = "";
            
        StreamSource prepMsg = new StreamSource(new StringReader(testSOAPRequest));
        SOAPPart sp = SOAPRequestTest.getSOAPPart();
        sp.setContent(prepMsg);
        soapContentString = testASAPSoapMessage.getSoapContent(SOAPRequestTest);
              
        assertTrue(soapContentString.equalsIgnoreCase(testSOAPRequest));
    }
    
    @Test
    public void testPrepareSOAPMessage() throws IOException{
        FileUtils.writeStringToFile(this.testFile,this.testSOAPRequest);
        assertTrue(testASAPSoapMessage.prepareSOAPMessage("testFile.xml").equalsIgnoreCase(testSOAPRequest));        
    }
    
    @Test
    public void testSendSOAPMessage() throws SOAPException, IOException{
        
        SOAPPart sp = replySOAPRequestTest.getSOAPPart();
        StreamSource prepMsg = new StreamSource(new StringReader(testReply));
        sp.setContent(prepMsg);
        
        SOAPConnection mockedSOAPConnection = mock(SOAPConnection.class);  
        when(mockedSOAPConnection.call(argThat(new IsSOAPMessage()), anyObject())).thenReturn(replySOAPRequestTest); 
        
        ASAPSoapMessage spyASAPSoapMessage = spy(new ASAPSoapMessage());
        when(spyASAPSoapMessage.getSoapConnection()).thenReturn(mockedSOAPConnection); 
        
        SOAPMessage replySOAPMessage= spyASAPSoapMessage.sendSOAPMessage(testSOAPRequest, testWebService, testSOAPAction);
        assertTrue(spyASAPSoapMessage.getSoapContent(replySOAPMessage).equalsIgnoreCase(testReply));     
    }
    
    class IsSOAPMessage extends ArgumentMatcher<SOAPMessage> {
        public boolean matches(Object soapMessage) {
            return soapMessage instanceof SOAPMessage;
        }
    }
}

本文转载自:http://blog.csdn.net/onlyqi/article/details/6546589

共有 人打赏支持
chace0120
粉丝 37
博文 47
码字总数 41091
作品 0
安阳
程序员
Mockito(三)--完整功能介绍

回到官网:http://mockito.org/,打开documentation可以看到原文。 强烈建议不熟悉Mockito的同学先看看我写的Mockito(一)入门篇和(二)实例篇之后再来看这篇文章。 因为只有看了前两篇文章才明...

chace0120 ⋅ 2014/04/01 ⋅ 0

5分钟了解Mockito

一、什么是mock测试,什么是mock对象? 先来看看下面这个示例: 从上图可以看出如果我们要对A进行测试,那么就要先把整个依赖树构建出来,也就是BCDE的实例。 一种替代方案就是使用mocks 从图...

闪电 ⋅ 2016/09/25 ⋅ 0

Kotlin 写 Android 单元测试(四),Robolectric 在 JVM 上测试安卓相关代码

Kotlin 写 Android 单元测试系列: Kotlin 写 Android 单元测试(一),单元测试是什么以及为什么需要 Kotlin 写 Android 单元测试(二),JUnit 4 测试框架和 kotlin.test 库的使用 Kotlin...

JohnnyShieh ⋅ 2017/12/20 ⋅ 0

mockito 模拟框架

今天无意中看到mockito 这个框架 一看原来是 模拟测试框架 Mockito尝试用不一样的方法做mocking测试,是简单轻量级能够替代EasyMock的框架。使用简单,测试代码可读性高,丰富的文档包含在j...

owensliu ⋅ 2014/11/04 ⋅ 0

Mockito 中文文档 三

27. 委托调用真实实例 (Since 1.9.5) 当使用常规的 spy API 去 mock 或者 spy 一个对象很困难时可以用 delegate 来 spy 或者 mock 对象的某一部分。 从 Mockito 的 1.10.11 版本开始, dele...

张贴在 ⋅ 2016/06/27 ⋅ 0

JAVA单元测试mock框架

JAVA单元测试mock框架 无标题2016-07-17298 阅读 JAVA 一.概述 最近在做代码重构,发现系统中的UT很少,重构没有UT的话,全部得人工测试,逻辑覆盖不一定全部能覆盖到,因此UT还是很有必要存...

无标题 ⋅ 2016/07/17 ⋅ 0

Java EE 单元测试

觉得测试 Java EE 应用程序太困难、不方便或者太复杂?通过阅读本文,您将了解现实情况并非如此,同时还将了解如何高效进行单元测试。 测试是 Java Platform, Enterprise Edition (Java EE) ...

justjavac ⋅ 2013/09/12 ⋅ 0

PowerMock和Mockito来mock

简单介绍如何使用PowerMock和Mockito来mock 1. 构造函数 2. 静态函数 3. 枚举实现的单例 4. 选择参... 时间 2015-06-16 21:15:05 BlogJava-技术区 原文 http://www.blogjava.net/usherlight...

yangming0322 ⋅ 2016/09/20 ⋅ 1

Kotlin 写 Android 单元测试(三),Mockito mocking 框架的使用

Kotlin 写 Android 单元测试系列: Kotlin 写 Android 单元测试(一),单元测试是什么以及为什么需要 Kotlin 写 Android 单元测试(二),JUnit 4 测试框架和 kotlin.test 库的使用 Kotlin...

JohnnyShieh ⋅ 2017/12/14 ⋅ 0

Java工具及框架汇总

如今软件的复杂度已经超过了程序员们理解的极限,我们在每日的编程中不需要从轮子造起,众多成熟稳定的框架可以帮我们简化开发,避免踩坑。 此文记录了我平时工作中常用的一些框架,及其简短...

rathan0 ⋅ 2016/01/15 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

CENTOS7防火墙命令记录

安装Firewall命令: yum install firewalld firewalld-config Firewall开启常见端口命令: firewall-cmd --zone=public --add-port=80/tcp --permanent firewall-cmd --zone=public --add-po......

cavion ⋅ 50分钟前 ⋅ 0

【C++】【STL】利用chromo来测量程序运行时间与日志时间打印精确到微秒

直接上代码吧,没啥好说的。头疼。 #include <iostream>#include <string>#include <ctime>#include <sstream>#include <iomanip>#include <thread>#include <chrono>using ......

muqiusangyang ⋅ 53分钟前 ⋅ 0

Mac环境下svn的使用

在Windows环境中,我们一般使用TortoiseSVN来搭建svn环境。在Mac环境下,由于Mac自带了svn的服务器端和客户端功能,所以我们可以在不装任何第三方软件的前提下使用svn功能,不过还需做一下简...

故久呵呵 ⋅ 今天 ⋅ 0

破解公司回应苹果“USB限制模式”:已攻破

本周四,苹果发表声明称 iOS 中加入了一项名为“USB 限制模式”的功能,可以防止 iPhone 在连接其他设备的时候被破解,并且强调这一功能并不是针对 FBI 等执法部门,为的是保护用户数据安全。...

六库科技 ⋅ 今天 ⋅ 0

MyBtais整合Spring Boot整合,TypeHandler对枚举类(enum)处理

概要 问题描述 我想用枚举类来表示用户当前状态,枚举类由 code 和 msg 组成,但我只想把 code 保存到数据库,查询处理,能知道用户当前状态,这应该怎么做呢?在 Spring 整合MyBatis 的时候...

Wenyi_Feng ⋅ 今天 ⋅ 0

synchronized与Lock的区别

# <center>王梦龙的读书笔记第一篇</center> ## <center>-synchronized与Lock的区别</centre> ###一、从使用场景来说 + synchronized 是能够注释代码块、类、方法但是它的加锁是和解锁使用一......

我不想加班 ⋅ 今天 ⋅ 0

VConsole的使用

手机端控制台打印输出,方便bug的排查。 首先需要引入vconsole.min.js 文件,然后在文件中创造实例。就能直接使用了。 var vConsole = new VConsole(); vConsole的文件地址...

大美琴 ⋅ 今天 ⋅ 0

Java NIO之字符集

1 字符集和编解码的概念 首先,解释一下什么是字符集。顾名思义,就是字符的集合。它的初衷是把现实世界的符号映射为计算机可以理解的字节。比如我创造一个字符集,叫做sex字符集,就包含两个...

士别三日 ⋅ 今天 ⋅ 0

Spring Bean基础

1、Bean之间引用 <!--如果Bean配置在同一个XML文件中,使用local引用--><ref bean="someBean"/><!--如果Bean配置在不同的XML文件中,使用ref引用--><ref local="someBean"/> 其实两种......

霍淇滨 ⋅ 今天 ⋅ 0

05、基于Consul+Upsync+Nginx实现动态负载均衡

1、Consul环境搭建 下载consul_0.7.5_linux_amd64.zip到/usr/local/src目录 cd /usr/local/srcwget https://releases.hashicorp.com/consul/0.7.5/consul_0.7.5_linux_amd64.zip 解压consu......

北岩 ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部