EasyMock与Junit的集成测试
转自 http://www.cnblogs.com/johnsonxu/archive/2011/07/18/2109616.html
(1)
EasyMock 是一套通过简单的方法对于指定的接口或类生成 Mock 对象的类库,它能利用对接口或类的模拟来辅助单元测试。Mock 方法是单元测试中常见的一种技术.
(1)
EasyMock 是一套通过简单的方法对于指定的接口或类生成 Mock 对象的类库,它能利用对接口或类的模拟来辅助单元测试。Mock 方法是单元测试中常见的一种技术.
主要作用:
模拟一些在应用中不容易构造或者比较复杂的对象,比如HttpServletRequest、 Connection等,从而把测试与测试边界以外的对象隔离开,真正的形成“单元测试”,专心测试业务逻辑(各个业务分支,即各个if..else),而不会因为依赖对象对测试产生影响。
模拟一些在应用中不容易构造或者比较复杂的对象,比如HttpServletRequest、 Connection等,从而把测试与测试边界以外的对象隔离开,真正的形成“单元测试”,专心测试业务逻辑(各个业务分支,即各个if..else),而不会因为依赖对象对测试产生影响。
主要应用场合:
一般来说,
1.对于目标对象中的合作者对象,在测试时如果其状态或行为的实现严重地依赖外部资源.比如:
数据库连接操作 -->依赖数据库连接
request请求 -->依赖用户发送请求
负责发送电子邮件的类 -->依赖外部触发
2.
或者团队并行开发时,目标对象的合作者对象并没有实现.比如
J2EE 中,横向分工时,
负责 Action 的调用 Service -->若相应的 Service没有实现
负责 Service 调用 DAO 时, -->若相应的 Service没有实现,
一般来说,
1.对于目标对象中的合作者对象,在测试时如果其状态或行为的实现严重地依赖外部资源.比如:
数据库连接操作 -->依赖数据库连接
request请求 -->依赖用户发送请求
负责发送电子邮件的类 -->依赖外部触发
2.
或者团队并行开发时,目标对象的合作者对象并没有实现.比如
J2EE 中,横向分工时,
负责 Action 的调用 Service -->若相应的 Service没有实现
负责 Service 调用 DAO 时, -->若相应的 Service没有实现,
这些我们就需要模仿这些类。
对于DAO层的测试--spring textContext来进行
说明:
可以看到的是,在 Service 层与 Web 层, Mock 对象能很好的被应用。
有人觉得在 Persistence 层也应该使用 Mock 对象,但就像我们所知道的,在使用 Hibernate 、 Ibatis 等 ORM 工具的情况下,我们的 Persistence 层的测试主要测试的就是那些配置文件、查询语句等.这时,最好是采用spring的测试框架testcontext,让其测试用例可以在不启动容器的情况下,为用例加载hibernate/ibatis/spring的配置文件,直接测试这些配置文件及数据库操作。
(2)
重要的概念
1.
在一个完整的测试过程中,一个 Mock 对象将会经历两个状态:Record 状态和 Replay 状态。Mock 对象一经创建,它的状态就被置为 Record。在 Record 状态,用户可以设定 Mock 对象的预期行为和输出,这些对象行为被录制下来,保存在 Mock 对象中。
可以看到的是,在 Service 层与 Web 层, Mock 对象能很好的被应用。
有人觉得在 Persistence 层也应该使用 Mock 对象,但就像我们所知道的,在使用 Hibernate 、 Ibatis 等 ORM 工具的情况下,我们的 Persistence 层的测试主要测试的就是那些配置文件、查询语句等.这时,最好是采用spring的测试框架testcontext,让其测试用例可以在不启动容器的情况下,为用例加载hibernate/ibatis/spring的配置文件,直接测试这些配置文件及数据库操作。
(2)
重要的概念
1.
在一个完整的测试过程中,一个 Mock 对象将会经历两个状态:Record 状态和 Replay 状态。Mock 对象一经创建,它的状态就被置为 Record。在 Record 状态,用户可以设定 Mock 对象的预期行为和输出,这些对象行为被录制下来,保存在 Mock 对象中。
2.
将 Mock 对象切换到 Replay 状态
在调用 replay() 方法之前的状态, EashMock 称之为 “record 状态 ” 。该状态下, Mock 对象不具备行为(即模拟接口的实现),它仅仅记录方法的调用。在调用 replay() 后,它才以 Mock 对象预期的行为进行工作,检查预期的方法调用是否真的完成。
将 Mock 对象切换到 Replay 状态
在调用 replay() 方法之前的状态, EashMock 称之为 “record 状态 ” 。该状态下, Mock 对象不具备行为(即模拟接口的实现),它仅仅记录方法的调用。在调用 replay() 后,它才以 Mock 对象预期的行为进行工作,检查预期的方法调用是否真的完成。
在使用 Mock 对象进行实际的测试前,我们需要将 Mock 对象的状态切换为 Replay。在 Replay 状态,Mock 对象能够根据设定对特定的方法调用作出预期的响应。将 Mock 对象切换成 Replay 状态有两种方式,您需要根据 Mock 对象的生成方式进行选择。如果 Mock 对象是通过 org.easymock.EasyMock 类提供的静态方法 createMock 生成的(第1节中介绍的第一种 Mock 对象生成方法),那么 EasyMock 类提供了相应的 replay 方法用于将 Mock 对象切换为 Replay 状态:
replay(mockResultSet);
replay(mockResultSet);
如果 Mock 对象是通过 IMocksControl 接口提供的 createMock 方法生成的(第1节中介绍的第二种Mock对象生成方法),那么您依旧可以通过 IMocksControl 接口对它所创建的所有 Mock 对象进行切换:control.replay();
3.
对 Mock 对象的行为进行验证
在利用 Mock 对象进行实际的测试过程之后,我们还有一件事情没有做:对 Mock 对象的方法调用的次数进行验证。
为了验证指定的方法调用真的完成了,我们需要调用 verify 方法进行验证。和 replay 方法类似,您需要根据 Mock 对象的生成方式来选用不同的验证方式。如果 Mock 对象是由 org.easymock.EasyMock 类提供的 createMock 静态方法生成的,那么我们同样采用 EasyMock 类的静态方法 verify 进行验证:
verify(mockResultSet);
对 Mock 对象的行为进行验证
在利用 Mock 对象进行实际的测试过程之后,我们还有一件事情没有做:对 Mock 对象的方法调用的次数进行验证。
为了验证指定的方法调用真的完成了,我们需要调用 verify 方法进行验证。和 replay 方法类似,您需要根据 Mock 对象的生成方式来选用不同的验证方式。如果 Mock 对象是由 org.easymock.EasyMock 类提供的 createMock 静态方法生成的,那么我们同样采用 EasyMock 类的静态方法 verify 进行验证:
verify(mockResultSet);
如果Mock对象是有 IMocksControl 接口所提供的 createMock 方法生成的,那么采用该接口提供的 verify 方法,例如第1节中的 IMocksControl 实例 control:
control.verify();
需要注意的地方:
control.verify();
需要注意的地方:
1.EasyMock 类的 createControl 方法能创建一个接口 IMocksControl 的对象,该对象能创建并管理多个 Mock 对象。如果需要在测试中使用多个 Mock 对象,我们推荐您使用这一机制,因为它在多个 Mock 对象的管理上提供了相对便捷的方法。
2.如果您要模拟的是一个具体类而非接口,那么您需要下载扩展包 EasyMock Class Extension 2.2.2。在对具体类进行模拟时,您只要用 org.easymock.classextension.EasyMock 类中的静态方法代替 org.easymock.EasyMock 类中的静态方法即可。
3.在一个完整的测试过程中,一个 Mock 对象将会经历两个状态:Record 状态和 Replay 状态。Mock 对象一经创建,它的状态就被置为 Record。在 Record 状态,用户可以设定 Mock 对象的预期行为和输出,这些对象行为被录制下来,保存在 Mock 对象中。
(3)
1、使用EasyMock的大体步骤
1、使用EasyMock的大体步骤
A.使用 EasyMock 生成 Mock 对象;
单个的Mock对象,利用静态导入EasyMock,通过createMock(interfaceName.class)
多个Mock对象,通过ImocksControl管理。
IMocksControl control = EasyMock.createControl();
java.sql.Connection mockConnection = control.createMock(Connection.class);
java.sql.Statement mockStatement = control.createMock(Statement.class);
单个的Mock对象,利用静态导入EasyMock,通过createMock(interfaceName.class)
多个Mock对象,通过ImocksControl管理。
IMocksControl control = EasyMock.createControl();
java.sql.Connection mockConnection = control.createMock(Connection.class);
java.sql.Statement mockStatement = control.createMock(Statement.class);
B.根据测试目的,设定 Mock 对象的预期行为和输出;
如以下各实例:
测试数据库查询-登录失败:则设置预期为:expect(rs.next()).andReturn(false);
如以下各实例:
测试数据库查询-登录失败:则设置预期为:expect(rs.next()).andReturn(false);
servlet判断用户信息登录失败:则设置预期为:expect(request.getParameter("password")).andReturn("pass");
即登录不对,从而测试登录判断失败的业务分支
即登录不对,从而测试登录判断失败的业务分支
所有实际代码执行的方法,都必须“录制”。-->重要!
C. 将 Mock 对象切换到 Replay 状态
单个Mock:replay(mockObj)
多个Mcok:control.replay()
单个Mock:replay(mockObj)
多个Mcok:control.replay()
D.利用 Mock 对象方法进行实际单元测试;
String res = login.login(conn, name, pas); //con是一个Connection的Mock对象
String res = login.login(conn, name, pas); //con是一个Connection的Mock对象
E.对 Mock 对象的行为进行验证。
单个Mock:verify(mockObj)
多个Mock:control.verify()
单个Mock:verify(mockObj)
多个Mock:control.verify()
三实例:(请见附件)
db连接的login测试
servlet请求测试
ssh中的service层测试
db连接的login测试
servlet请求测试
ssh中的service层测试