使用Mock进行业务逻辑层Service测试详解
作者:疯狂的帆
场景
公司采用的是分层开发,controller、Service、dao层分离,现在写dao层代码的人生病了,进度比较慢,现在你写的是 Service层的代码,怎么测试 Service 层代码是否正确呢?
Service层测试的重点是什么?
- DAO层调用的次数
- 以及调用的顺序
- 并不关心最后数据是否准确
mock是什么?
在软件测试中,mock是一种模拟对象的技术,用于在测试过程中替代真实的对象。
通过mock,我们可以控制被模拟对象的行为和返回值,以便进行更加精确的测试。
测试代码示例
准备环境
引入依赖
<!-- Junit测试包 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13</version>
</dependency>
<!-- 专门用来做业务逻辑层 或者 Controller层的测试的 -->
<dependency>
<groupId>org.easymock</groupId>
<artifactId>easymock</artifactId>
<version>3.5.1</version>
</dependency>准备Dao层测试接口,不需要方法的实现
public interface AaDao {
void a();
void b();
}public interface BbDao {
void c();
void d();
}service 测试代码
public interface ABService {
void aa();
void bb();
void cc();
void dd();
}testService 在此方法中使用 mock 进行测试
public class TestService {
private ABService abService = new ABServiceImpl();
}1. 简单测试 createMock
@Override
public void aa() {
aDao.a();
}测试代码
@Test
public void testAA() {
// 创建对象
AaDao aaDao = EasyMock.createStrictMock(AaDao.class);
// 记录
aaDao.a();
EasyMock.expectLastCall();
// 使能设置
EasyMock.replay(aaDao);
// 接下来调用Service进行测试
abService.setaDao(aaDao);
abService.aa();
// 进行校验
EasyMock.verify(aaDao);
}2. 测试调用顺序 createStrictMock
@Override
public void ee() {
aDao.b();
aDao.a();
}测试代码1
// 测试调用顺序
@Test
public void testEE1() {
// 创建对象
AaDao aaDao = EasyMock.createMock(AaDao.class);
// 进行记录
aaDao.a();
EasyMock.expectLastCall();
aaDao.b();
EasyMock.expectLastCall();
// 使能设置,保存记录信息
EasyMock.replay(aaDao);
// 调用 Service 测试
abService.setaDao(aaDao);
abService.ee();
// 进行校验
EasyMock.verify(aaDao);
}运行此代码,结果竟然是正确的,明明调用顺序不一致,却还是正确,这显然是不对的
测试代码2 使用createStrictMock
@Test
public void testEE2() {
// 创建对象
AaDao aaDao = EasyMock.createStrictMock(AaDao.class);
// 进行记录
aaDao.b();
EasyMock.expectLastCall();
aaDao.a();
EasyMock.expectLastCall();
// 使能设置,保存记录信息
EasyMock.replay(aaDao);
// 调用 Service 测试
abService.setaDao(aaDao);
abService.ee();
// 进行校验
EasyMock.verify(aaDao);
}3. 测试方法多次调用以及调用顺序
@Override
public void bb() {
aDao.a();
aDao.b();
aDao.b();
aDao.a();
}测试代码
@Test
public void testBB() {
// 创建对象
AaDao aaDao = EasyMock.createStrictMock(AaDao.class);
// 记录
aaDao.a();
EasyMock.expectLastCall();
aaDao.b();
EasyMock.expectLastCall();
aaDao.b();
EasyMock.expectLastCall();
aaDao.a();
EasyMock.expectLastCall();
// 使能设置,即保存记录信息
EasyMock.replay(aaDao);
// 调用 Service 测试
abService.setaDao(aaDao);
abService.bb();
// 进行校验
EasyMock.verify(aaDao);
}如果是多次调用的话,就需要书写多次记录
4. 测试调用不同dao的方法
@Override
public void cc() {
aDao.a();
bDao.c();
}测试代码1
@Test
public void testCC1() {
// 创建对象
AaDao aaDao = EasyMock.createStrictMock(AaDao.class);
BbDao bbDao = EasyMock.createStrictMock(BbDao.class);
// 进行记录
bbDao.c();
EasyMock.expectLastCall();
aaDao.a();
EasyMock.expectLastCall();
// 使能设置,保存记录信息
EasyMock.replay(aaDao, bbDao);
// 调用 Service 测试
abService.setaDao(aaDao);
abService.setbDao(bbDao);
abService.cc();
// 进行校验
EasyMock.verify(aaDao, bbDao);
}可以看出来,createStrictMock方法并不能保证多个 dao之间的调用顺序,只能对单个的DAO的调用顺序有严格的要求
测试代码2 createStrictControl
@Test
public void testCC2() {
// 创建一个 controller,约束这些dao是一个整体
IMocksControl control = EasyMock.createStrictControl();
// 创建对象
AaDao aaDao = control.createMock(AaDao.class);
BbDao bbDao = control.createMock(BbDao.class);
// 进行记录
aaDao.a();
EasyMock.expectLastCall();
bbDao.c();
EasyMock.expectLastCall();
// 使能设置,保存记录信息
control.replay();
// 调用 Service 测试
abService.setaDao(aaDao);
abService.setbDao(bbDao);
abService.cc();
// 进行校验
control.verify();
}使用 createStrictControl 定义一个整体,进行多个 dao 的测试
5. 测试不同dao调用顺序及次数
@Override
public void dd() {
aDao.a();
bDao.c();
bDao.d();
aDao.a();
}测试代码
@Test
public void testDD() {
// 创建一个 controller,约束这些dao是一个整体
IMocksControl control = EasyMock.createStrictControl();
// 创建对象
AaDao aaDao = control.createMock(AaDao.class);
BbDao bbDao = control.createMock(BbDao.class);
// 进行记录
aaDao.a();
EasyMock.expectLastCall();
bbDao.c();
EasyMock.expectLastCall();
bbDao.d();
EasyMock.expectLastCall();
aaDao.a();
EasyMock.expectLastCall();
// 使能设置,保存记录信息
control.replay();
// 调用 Service 测试
abService.setaDao(aaDao);
abService.setbDao(bbDao);
abService.dd();
// 进行校验
control.verify();
}测试此方法时,即便是调换 同一个dao的方法也会报错,满足条件
总结
测试 service 层时,可以使用 mock 框架进行测试,引入 mock依赖即可,操作简单
如果测试的 service 只包含一个dao,那么使用 EasyMock.createStrictMock() 即可进行测试
如果测试的 service 包含多个dao,那么使用 EasyMock.createStrictControl(); 创建一个 control 进行包裹即可测试
到此这篇关于使用Mock进行业务逻辑层Service测试详解的文章就介绍到这了,更多相关Mock测试Service内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
