junit使用mock objects进行单元测试
上一篇我介绍了使用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进行单元测试的更多相关文章
- 换种思路写Mock,让单元测试更简单
开篇引入 单元测试中的Mock方法,通常是为了绕开那些依赖外部资源或无关功能的方法调用,使得测试重点能够集中在需要验证和保障的代码逻辑上.在定义Mock方法时,开发者真正关心的只有一件事:" ...
- 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", ...
- 学习笔记:首次进行JUnit+Ant构建自动的单元测试(二)
关键字:JUnit,Ant,单元测试 终于把JUnit+Ant构建单元测试的大概了解了,其实我实践的过程是对了,只是指导博客(看到这里不懂请看我上一篇博客)本身的错误“成功”把我带入“坑”,有时候网友 ...
- 学习笔记:首次进行JUnit+Ant构建自动的单元测试(一)
指导博客:https://blog.csdn.net/Cceking/article/details/51692010 基于软件测试的需求,使用JUnit+Ant构建自动的单元测试. IDE:ecli ...
- 有效使用Mock编写java单元测试
Java单元测试对于开发人员质量保证至关重要,尤其当面对一团乱码的遗留代码时,没有高覆盖率的单元测试做保障,没人敢轻易对代码进行重构.然而单元测试的编写也不是一件容易的事情,除非使用TDD方式,否则编 ...
- 使用junit进行最简单的单元测试
使用junit进行最简单的单元测试 使用工具: jdk IDEA Maven 第一步 创建一个Maven项目 第二步 导入junit依赖 <dependency> <groupId& ...
- 【java测试】Junit、Mock+代码覆盖率
原文见此处 单元测试是编写测试代码,用来检测特定的.明确的.细颗粒的功能.单元测试并不一定保证程序功能是正确的,更不保证整体业务是准备的. 单元测试不仅仅用来保证当前代码的正确性,更重要的是用来保证代 ...
- 使用 Python Mock 类进行单元测试
数据类型.模型或节点——这些都只是mock对象可承担的角色.但mock在单元测试中扮演一个什么角色呢? 有时,你需要为单元测试的初始设置准备一些“其他”的代码资源.但这些资源兴许会不可用,不稳定,或者 ...
- 使用Python中的mock模块进行单元测试
在进行单元测试的时候,有时候会遇到这种情况: 出于某些原因,我们不想测试某一部分内容,但是我们想要测试的部分却依赖这部分内容. 这时候,可以使用mock模块来模拟调用这部分内容,并给出返回结果,举例如 ...
- JUNIT -- springMVC的action进行单元测试
原文:http://blog.csdn.net/gaopeng0071/article/details/49946575 我开发环境springMVC版本3.0.4 样例代码: package com ...
随机推荐
- [转帖]WinXP添加TLS1.1、TLS1.2支持
现象 HTTPS服务在Win7及Win10能够正常打开,但是在XP下用IE浏览器却无法打开,XP下用第三方浏览器(我试了谷歌浏览器)却能正常打开.经过抓包分析,用IE浏览器是协商用的是TLS1而用第三 ...
- 【转帖】text-davinci-003和ChatGPT之间的不同点
https://zhuanlan.zhihu.com/p/603709081 先看下GPT的发展时间线 InstructGPT(2022 年 1 月)是一系列 GPT-3 模型(包括 text-dav ...
- [转帖]yum 下载全量依赖 rpm 包及离线安装(终极解决方案)
简介 通常生产环境由于安全原因都无法访问互联网.此时就需要进行离线安装,主要有两种方式:源码编译.rpm包安装.源码编译耗费时间长且缺乏编译环境,所以一般都选择使用离线 rpm 包安装. 验证环境 C ...
- [转帖]nmon使用及监控数据分析
[使用] [监控数据分析] 参考链接:nmon监控数据分析 性能测试中,各个服务器资源占用统计分析是一个很重要的组成部分,通常我们使用nmon这个工具来进行监控以及监控结果输出. 一.在监控阶段使用类 ...
- [转帖]CPU Utilization is Wrong
Brendan Gregg's Blog home CPU Utilization is Wrong 09 May 2017 The metric we all use for CPU utiliza ...
- 巧用GenericObjectPool创建自定义对象池
作者:京东物流 高圆庆 1 前言 通常一个对象创建.销毁非常耗时的时候,我们不会频繁的创建和销毁它,而是考虑复用.复用对象的一种做法就是对象池,将创建好的对象放入池中维护起来,下次再用的时候直接拿池中 ...
- 爬虫逆向基础,认识 SM1-SM9、ZUC 国密算法
关注微信公众号:K哥爬虫,QQ交流群:808574309,持续分享爬虫进阶.JS/安卓逆向等技术干货! [01x00] 简介 国密即国家密码局认定的国产加密算法,爬虫工程师在做 JS 逆向的时候,会遇 ...
- Gin 路由注册与请求参数获取
目录 一.Web应用开发的两种模式 1.前后端不分离模式 2.前后端分离模式 二.RESTful介绍 三.API接口 3.1 RESTful API设计指南 3.2 API与用户的通信协议 3.3 R ...
- 【二】AI Studio 项目详解【VisualDL工具、(二)环境使用说明、(二)脚本任务、图形化任务、在线部署及预测】PARL
相关文章 [一]-环境配置+python入门教学 [二]-Parl基础命令 [三]-Notebook.&pdb.ipdb 调试 [四]-强化学习入门简介 [五]-Sarsa&Qlear ...
- Linux的信号管理 [补档-2023-07-30]
信号 11-1简介: 信号只是表示某个信号,不可以携带大量信息,信号需要满足特点的条件才会产生.是一种特别的通信手 段. 11-2 信号机制: 假设有两个进程A,B,现在进程A给进程B发送信号 ...
