24分钟学会用JMock进行单元测试

发表于:2008-7-16 16:51

字体: | 上一篇 | 下一篇 | 我要投稿

 作者:未知    来源:IT168

  不管是测试驱动开发或者是其它的开发模式,都会需要对代码进行单元测试,对于关联依赖关系少或者比较简单的类来说,直接使用JUnit就可以轻松的完成测试工作,但是对于关联到其它比较复杂的类或对运行环境有要求的类的单元测试,比如ejb,servlet或Dao等,测试起来或者需要配置特定的环境,或者十分耗时,给单元测试造成困难。在这里介绍使用JMock来模拟那些不需要测试的类,帮助完成有单元测试。<

  例如,有这样两个类,一个是Dao.java,用于数据库访问成操作的,一个是Business.java,需要调用Dao进行业务处理。Dao.java是已经在有数据库的环境测试通过的,现在需要测试Business.java。通常情况下,我们需要在测试环境配置好数据库连接环境,并且需要准备数据后,才可以开始Business.java的测试,现在如果通过JMock就可以不配置数据库环境,也可以完成测试。

//Dao.java

  package com.raistlin.test.jmock
  public class Dao
  {
  public Dao()
  {
  }
  public List execute(String sql)
  {
  //数据库操作...

  }
  }
  //Business.java

  package com.raistlin.test.jmock
  public class Business
  {
  private Dao dao ;
  public void setDao(Dao dao)
  {
  this.dao = dao;
  }
  public String operate()
  {
  List list = dao.execute("select * from tbl_test");
  return (String) list.get(0);
  }
  }
  //BusinessTest.java

  package com.raistlin.test.jmock
  import org.jmock.cglib.MockObjectTestCase;
  import org.jmock.cglib.Mock;
  public class BusinessTest extends MockObjectTestCase
  {
  private Mock mockDao = null;
  private Business business = null;
  protected void setUp() throws Exception
  {
  super.setUp();
  mockDao = new Mock(Dao.class);
  business = new Business();
  }
  protected void tearDown() throws Exception
  {
  mockDao = null;
  business = null;
  super.tearDown();
  }
  public void testOperate()
  {
  ArrayList stubList = new ArrayList();
  stubList.add("test");
  // 定义Mock剧本

  mockDao.expects(once())// 期待次数

  .method//Dao.java

  package com.raistlin.test.jmock
  public class Dao
  {
  public Dao()
  {
  }
  public List execute(String sql)
  {
  //数据库操作...

  }
  }
  //Business.java

  package com.raistlin.test.jmock
  public class Business
  {
  private Dao dao ;
  public void setDao(Dao dao)
  {
  this.dao = dao;
  }
  public String operate()
  {
  List list = dao.execute("select * from tbl_test");
  return (String) list.get(0);
  }
  }
  //BusinessTest.java

  package com.raistlin.test.jmock
  import org.jmock.cglib.MockObjectTestCase;
  import org.jmock.cglib.Mock;
  public class BusinessTest extends MockObjectTestCase
  {
  private Mock mockDao = null;
  private Business business = null;
  protected void setUp() throws Exception
  {
  super.setUp();
  mockDao = new Mock(Dao.class);
  business = new Business();
  }
  protected void tearDown() throws Exception
  {
  mockDao = null;
  business = null;
  super.tearDown();
  }
  public void testOperate()
  {
  ArrayList stubList = new ArrayList();
  stubList.add("test");
  // 定义Mock剧本

  mockDao.expects(once())// 期待次数

  .method("execute")// 调用方法

  .with(eq("select * from tbl_test"))// 传入参数等于

  .will(this.returnValue(stubList));// 返回对象

  Dao dao = (Dao) mockDao.proxy();
  business.setDao(dao);
  assertEquals(business.operate(), "test");
  }
  }
("execute")// 调用方法

  .with(eq("select * from tbl_test"))// 传入参数等于

  .will(this.returnValue(stubList));// 返回对象

  Dao dao = (Dao) mockDao.proxy();
  business.setDao(dao);
  assertEquals(business.operate(), "test");
  }
  }


1

  在工程中导入jmock-1.0.1.jar ,jmock-cglib-1.0.1.jar ,cglib-full-2.0.jar 三个jar包,然后在JUnit中执行BusinessTest.java,会显示绿棒,这样,在没有数据库的情况下,单元测试成功。

  使用JMock模拟类的条件:

  1、要有无参数的构造器;

  2、构造器是public;

  这样对于private的构造器或单例模式的类应该是无法模拟了。这样就要求我们养成针对接口编程的习惯,对接口用JMock进行模拟将不受这些限制。只需要将

  import org.jmock.cglib.MockObjectTestCase;

  import org.jmock.cglib.Mock;

  改为

  import org.jmock.MockObjectTestCase;

  import org.jmock.Mock;

  即可。

  对于Mock类,有很多API可供使用,比如:

  isA(Class clz) 表示为某个类

  isVoid() 将will()换成isVoid()表示无返回值

  详细API可以参考一下DOC,还会找到很多有用的东西。

《2023软件测试行业现状调查报告》独家发布~

关注51Testing

联系我们

快捷面板 站点地图 联系我们 广告服务 关于我们 站长统计 发展历程

法律顾问:上海兰迪律师事务所 项棋律师
版权所有 上海博为峰软件技术股份有限公司 Copyright©51testing.com 2003-2024
投诉及意见反馈:webmaster@51testing.com; 业务联系:service@51testing.com 021-64471599-8017

沪ICP备05003035号

沪公网安备 31010102002173号