单元测试与 Mock 方法
单元测试是对应用中的某一个模块的功能进行验证。在单元测试中,我们常遇到的问题是应用中其它的协同模块尚未开发完成,或者被测试模块需要和一些不容易构造、比较复杂的对象进行交互。另外,由于不能肯定其它模块的正确性,我们也无法确定测试中发现的问题是由哪个模块引起的。
Mock 对象能够模拟其它协同模块的行为,被测试模块通过与 Mock 对象协作,可以获得一个孤立的测试环境。此外,使用 Mock 对象还可以模拟在应用中不容易构造(如 HttpServletRequest 必须在 Servlet 容器中才能构造出来)和比较复杂的对象(如 JDBC 中的 ResultSet 对象),从而使测试顺利进行。
EasyMock 简介
手动的构造 Mock 对象会给开发人员带来额外的编码量,而且这些为创建 Mock 对象而编写的代码很有可能引入错误。目前,有许多开源项目对动态构建 Mock 对象提供了支持,这些项目能够根据现有的接口或类动态生成,这样不仅能避免额外的编码工作,同时也降低了引入错误的可能。
EasyMock 是一套用于通过简单的方法对于给定的接口生成 Mock 对象的类库。它提供对接口的模拟,能够通过录制、回放、检查三步来完成大体的测试过程,可以验证方法的调用种类、次数、顺序,可以令 Mock 对象返回指定的值或抛出指定异常。通过 EasyMock,我们可以方便的构造 Mock 对象从而使单元测试顺利进行
1 下载easymock的jar包。
2 在spring的配置文件中 添加
<bean id="userDao" class="org.easymock.EasyMock" factory-method="createStrictMock" >
<constructor-arg value="com.topsec.cms.dao.IUserDao"></constructor-arg>
</bean>
使用easymock的静态方法createStrictMock方法创建mock对象 ,传入dao层的dao接口,模拟dao层的实现。
通过 EasyMock,我们可以为指定的接口动态的创建 Mock 对象,并利用 Mock 对象来模拟协同模块或是领域对象,从而使单元测试顺利进行。这个过程大致可以划分为以下几个步骤:
- 使用 EasyMock 生成 Mock 对象;
- 设定 Mock 对象的预期行为和输出;
- 将 Mock 对象切换到 Replay 状态;
- 调用 Mock 对象方法进行单元测试;
- 对 Mock 对象的行为进行验证。
测试代码
reset(userDao);//重置userDao状态
userDao.deleteUserRole(1); //设置预期行为
expectLastCall();
userDao.deleteUserGroup(1);
expectLastCall();
userDao.delete(1);
expectLastCall();
replay(userDao);//修改userDao状态record到replay,在replay状态下 ,mock对象能够根据设定对特定方法的调用作出预期的响应
userService.deleteUser(1);
verify(userDao); //验证record状态下的mock对象的预期行为和输出是否与replay下mock对象的行为及输出一致 ,一致的话就通过测试 否则就报错,测试不通过