上一篇我介绍了使用stub进行单元测试。那么mock objects和stub有何区别?什么情况下使用mock objects呢?

下面摘自junit in action书中的解释:

mock objects (或者简称为 mocks),非常适用于将某一部分代码与其他代问隔离开来,并对这部分代码进行测试。

mocks 替换了测试中与你的方法协作的对象,从而提供个隔离层。从这一点来讲,它与 stub 有些类似。不过相似之处也仅限于

此,因为mocks 并不实现任何逻辑 它们只是提供了一种使测试能够控制仿造类的所有业务逻辑方法行为的方法的空壳。

下面以一个账户转账的测试用例加以说明。大家可以比较下其与stub的区别。

创建账户类

package com.lhy.junitkaifa.mocks.account;

/**
* 账户
*
* @author xusucheng
* @create 2018-12-22
**/
public class Account {
private String accountId;
private long balance; public Account(String accountId, long balance){
this.accountId = accountId;
this.balance = balance;
} public void debit(long amount){
this.balance-=amount;
} public void credit(long amount){
this.balance+=amount;
} public long getBalance(){
return this.balance;
}
}

创建配置接口与实现

package com.lhy.junitkaifa.mocks.configurations;

/**
* 配置
*
* @author xusucheng
* @create 2018-12-22
**/
public interface Configuration {
String getSQL(String sqlString);
}
package com.lhy.junitkaifa.mocks.configurations;

/**
* @author xusucheng
* @create 2018-12-22
**/
public class DefaultConfiguration implements Configuration {
public DefaultConfiguration(String configuration){ } @Override
public String getSQL(String sqlString) {
return null;
}
}

创建账户管理接口与实现

package com.lhy.junitkaifa.mocks.account;

/**
* 账户管理接口
*
* @author xusucheng
* @create 2018-12-22
**/
public interface AccountManager {
Account findAccountById(String userId); void updateAccount(Account account);
}
package com.lhy.junitkaifa.mocks.account;

import com.lhy.junitkaifa.mocks.configurations.Configuration;
import com.lhy.junitkaifa.mocks.configurations.DefaultConfiguration;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; /**
* 账户管理接口实现
*
* @author xusucheng
* @create 2018-12-22
**/
public class AccountManagerImpl implements AccountManager {
private Log logger; private Configuration configuration; public AccountManagerImpl(){
this(LogFactory.getLog(AccountManagerImpl.class),new DefaultConfiguration("technical"));
} public AccountManagerImpl(Log logger, Configuration configuration){
this.logger = logger;
this.configuration = configuration;
} @Override
public Account findAccountById(String userId) {
this.logger.debug("Getting account for user["+userId+"]");
this.configuration.getSQL("FIND_ACCOUNT_BY_ID"); return null;
} @Override
public void updateAccount(Account account) {
//Do nothing.
} }

创建账户管理服务类

package com.lhy.junitkaifa.mocks.account;

/**
* 账户管理服务
*
* @author xusucheng
* @create 2018-12-22
**/
public class AccountService {
private AccountManager accountManager; /**
* 注入具体实现
* @param accountManager
*/
public void setAccountManager(AccountManager accountManager){
this.accountManager = accountManager;
} public void transfer(String fromId, String toId, long amount){
//转出账户
Account from = this.accountManager.findAccountById(fromId);
//转入账户
Account to = this.accountManager.findAccountById(toId);
from.debit(amount);
to.credit(amount);
this.accountManager.updateAccount(from);
this.accountManager.updateAccount(to);
}
}

创建测试用账户管理接口

package com.lhy.junitkaifa.mocks.account;

import java.util.HashMap;
import java.util.Map; /**
* @author xusucheng
* @create 2018-12-22
**/
public class MockAccountManager implements AccountManager{
//保存所有账户
private Map<String,Account> accounts = new HashMap<>(); /**
* 添加账户
* @param userId
* @param account
*/
public void addAccount(String userId, Account account){
this.accounts.put(userId,account);
} /**
* 获取账户
* @param userId
* @return
*/
@Override
public Account findAccountById(String userId) {
return this.accounts.get(userId);
} @Override
public void updateAccount(Account account) {
//不干事
}
}

创建测试用日志类

package com.lhy.junitkaifa.mocks.account;

import org.apache.commons.logging.Log;

/**
* @author xusucheng
* @create 2018-12-22
**/
public class MockLog implements Log {
@Override
public boolean isFatalEnabled() {
return false;
} @Override
public boolean isErrorEnabled() {
return false;
} @Override
public boolean isWarnEnabled() {
return false;
} @Override
public boolean isInfoEnabled() {
return false;
} @Override
public boolean isDebugEnabled() {
return false;
} @Override
public boolean isTraceEnabled() {
return false;
} @Override
public void fatal(Object o) { } @Override
public void fatal(Object o, Throwable throwable) { } @Override
public void error(Object o) { } @Override
public void error(Object o, Throwable throwable) { } @Override
public void warn(Object o) { } @Override
public void warn(Object o, Throwable throwable) { } @Override
public void info(Object o) { } @Override
public void info(Object o, Throwable throwable) { } @Override
public void debug(Object o) { } @Override
public void debug(Object o, Throwable throwable) { } @Override
public void trace(Object o) { } @Override
public void trace(Object o, Throwable throwable) { }
}

创建测试用配置类

package com.lhy.junitkaifa.mocks.configurations;

/**
* @author xusucheng
* @create 2018-12-22
**/
public class MockConfiguration implements Configuration {
public void setSQL(String sqlString){ } @Override
public String getSQL(String sqlString) {
return null;
}
}

创建测试类

package com.lhy.junitkaifa.mocks.account;

import org.junit.Test;

import static org.junit.Assert.assertEquals;

/**
* @author xusucheng
* @create 2018-12-22
**/
public class TestAccountService {
@Test
public void testTransferOk(){
MockAccountManager mockAccountManager = new MockAccountManager();
Account from = new Account("1",200);
Account to = new Account("2",100);
mockAccountManager.addAccount("1", from);
mockAccountManager.addAccount("2", to); AccountService accountService = new AccountService();
accountService.setAccountManager(mockAccountManager);
accountService.transfer("1","2",50); assertEquals(150,from.getBalance());
assertEquals(150,to.getBalance());
}
}

运行测试

junit使用mock objects进行单元测试的更多相关文章

  1. 换种思路写Mock,让单元测试更简单

    开篇引入 单元测试中的Mock方法,通常是为了绕开那些依赖外部资源或无关功能的方法调用,使得测试重点能够集中在需要验证和保障的代码逻辑上.在定义Mock方法时,开发者真正关心的只有一件事:" ...

  2. What is the purpose of mock objects?

    Since you say you are new to unit testing and asked for mock objects in "layman's terms", ...

  3. 学习笔记:首次进行JUnit+Ant构建自动的单元测试(二)

    关键字:JUnit,Ant,单元测试 终于把JUnit+Ant构建单元测试的大概了解了,其实我实践的过程是对了,只是指导博客(看到这里不懂请看我上一篇博客)本身的错误“成功”把我带入“坑”,有时候网友 ...

  4. 学习笔记:首次进行JUnit+Ant构建自动的单元测试(一)

    指导博客:https://blog.csdn.net/Cceking/article/details/51692010 基于软件测试的需求,使用JUnit+Ant构建自动的单元测试. IDE:ecli ...

  5. 有效使用Mock编写java单元测试

    Java单元测试对于开发人员质量保证至关重要,尤其当面对一团乱码的遗留代码时,没有高覆盖率的单元测试做保障,没人敢轻易对代码进行重构.然而单元测试的编写也不是一件容易的事情,除非使用TDD方式,否则编 ...

  6. 使用junit进行最简单的单元测试

    使用junit进行最简单的单元测试 使用工具: jdk IDEA Maven 第一步 创建一个Maven项目 第二步 导入junit依赖 <dependency> <groupId& ...

  7. 【java测试】Junit、Mock+代码覆盖率

    原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代 ...

  8. 使用 Python Mock 类进行单元测试

    数据类型.模型或节点——这些都只是mock对象可承担的角色.但mock在单元测试中扮演一个什么角色呢? 有时,你需要为单元测试的初始设置准备一些“其他”的代码资源.但这些资源兴许会不可用,不稳定,或者 ...

  9. 使用Python中的mock模块进行单元测试

    在进行单元测试的时候,有时候会遇到这种情况: 出于某些原因,我们不想测试某一部分内容,但是我们想要测试的部分却依赖这部分内容. 这时候,可以使用mock模块来模拟调用这部分内容,并给出返回结果,举例如 ...

  10. JUNIT -- springMVC的action进行单元测试

    原文:http://blog.csdn.net/gaopeng0071/article/details/49946575 我开发环境springMVC版本3.0.4 样例代码: package com ...

随机推荐

  1. 百度网盘(百度云)SVIP超级会员共享账号每日更新(2023.12.18)

    一.百度网盘SVIP超级会员共享账号 可能很多人不懂这个共享账号是什么意思,小编在这里给大家做一下解答. 我们多知道百度网盘很大的用处就是类似U盘,不同的人把文件上传到百度网盘,别人可以直接下载,避免 ...

  2. 今天是个好日子,TaxCore(POS软件)备案指北

    POS软件是什么?你好意思吗,还在用老掉牙的Winform. 关于POS 销售终端--POS(point of sale)是一种多功能终端,把它安装在信用卡的特约商户和受理网点中与计算机联成网络,就能 ...

  3. 【转】国产飞腾D2000:基于A72?

    https://zhuanlan.zhihu.com/p/612054128 China's Phytium D2000: Building on A72? 国产飞腾D2000:基于A72? PS:麒 ...

  4. [转帖] 容器内的Linux诊断工具0x.tools

    https://www.cnblogs.com/codelogs/p/16242999.html 原创:扣钉日记(微信公众号ID:codelogs),欢迎分享,转载请保留出处. 简介# Linux上有 ...

  5. 【转帖】route命令详解大全(route命令使用实例)

    https://www.cxdtop.cn/n/225987.html 在实际的网络应用中,我们可能会遇到这样的网络环境,上外网我们使用的无线网络,内网我们使用的是有限网卡.在设置完成后会出现外网和内 ...

  6. [转帖]linux时间戳转换成时间指令_时间戳转换公式

    原文地址:http://wanping.blogbus.com/logs/28663569.html 1.时间戳转换为正常显示的时间格式 Freebsd 系统下: 转换命令为: date -r 111 ...

  7. [转帖]Nginx-https证书认证详解

    https://developer.aliyun.com/article/885650?spm=a2c6h.24874632.expert-profile.306.7c46cfe9h5DxWK 简介: ...

  8. 源码补丁神器—patch-package

    一.背景 vue项目中使用 vue-pdf第三方插件预览pdf,书写业务代码完美运行,pdf文件内容正常预览无问题.后期需求有变,业务需求增加电子签章功能.这个时候pdf文件的内容可以显示出来,但是公 ...

  9. MySQL【五】与python交互

    1.安装pymysql 安装pymysql pip install pymysql 2.游标(cursor)的使用 cursor,就是一个标识,用来标识数据可以理解成数组中的下标  . 一.声明一个游 ...

  10. 7.2 Windows驱动开发:内核注册并监控对象回调

    在笔者上一篇文章<内核枚举进程与线程ObCall回调>简单介绍了如何枚举系统中已经存在的进程与线程回调,本章LyShark将通过对象回调实现对进程线程的句柄监控,在内核中提供了ObRegi ...