测试工作(3 -- EasyMock与Junit4学习整理)

89510091 2009-10-30

EasyMock与Junit的集成测试

EasyMock是一套通过简单的方法对于指定的接口或类生成Mock对象的类库,它能利用对接口或类的模拟来辅助单元测试。Mock方法是单元测试中常见的一种技术,它的主要作用是模拟一些在应用中不容易构造或者比较复杂的对象,比如HttpServletRequest、Connection等,从而把测试与测试边界以外的对象隔离开,真正的形成“单元测试”,而不会因为依赖对象对测试产生影响。

1、使用EasyMock的大体步骤

A.使用EasyMock生成Mock对象;

单个的Mock对象,利用静态导入EasyMock,通过createMock(interfaceName.class)

多个Mock对象,通过ImocksControl管理。

IMocksControlcontrol=EasyMock.createControl();

java.sql.ConnectionmockConnection=control.createMock(Connection.class);

java.sql.StatementmockStatement=control.createMock(Statement.class);

B.设定Mock对象的预期行为和输出;比如一个PreparedStatement的Mock对象pst

expect(pst.executeQuery()).andReturn(rs);

pst.close();

所有实际代码执行的方法,都必须“录制”。

D.将Mock对象切换到Replay状态

单个Mock:replay(mockObj)

多个Mcok:control.replay()

E.利用Mock对象方法进行实际单元测试;

Stringres=login.login(conn,name,pas);//con是一个Connection的Mock对象

F.对Mock对象的行为进行验证。

单个Mock:verify(mockObj)

多个Mock:control.verify()

附:利用EasyMock生成数据库连接简单测试示例
package demo.mock;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;


public class LoginAction{
	
	public String login(Connection conn, String name, int pas) {
		
		PreparedStatement pst = null;
		ResultSet rs = null;
		
		try {
			String sql = "select * from user where name = ? and pas = ?";
			pst = conn.prepareStatement(sql);
			pst.setString(1, name);
			pst.setInt(2, pas);
			rs = pst.executeQuery();
			
			if(rs.next()) {
				return "登陆成功。";
			} else {
				return "登陆失败。";
			}
			
		}catch(SQLException e) {
			e.printStackTrace();
			return "抛出异常。";
		} finally {		
			try {
				rs.close();
				pst.close();
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
	}

}


package demo.mock;

import static org.easymock.EasyMock.createControl;
import static org.easymock.EasyMock.expect;
import static org.junit.Assert.assertEquals;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import org.easymock.IMocksControl;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class LoginActionTest {
	
	private LoginAction login;
	
	@Before
	public void init() {
		login = new LoginAction();
	}
	
	@After
	public void destory() {
		login = null;
	}

	@Test
	public void login() throws SQLException{
		String name = "admin";
		int pas = 123;
		
		//创建Mock对象
		IMocksControl control = createControl(); //创建多个Mock对象时通过IMocksControl管理

		Connection conn = control.createMock(Connection.class);
		PreparedStatement pst = control.createMock(PreparedStatement.class);
		ResultSet rs = control.createMock(ResultSet.class);

		// 录制信息,即设定Mock对象的预期行为和输出
		// 所有Mock对象需要执行的方法都必须录制,如pst.setInt(2, pas)、rs.close()等
		String sql = "select * from user where name = ? and pas = ?";
		expect(conn.prepareStatement(sql)).andReturn(pst).times(1);	 
		
		pst.setString(1, name);
		pst.setInt(2, pas);
		
		expect(pst.executeQuery()).andReturn(rs);
		expect(rs.next()).andReturn(true);
		
		
		rs.close();
		pst.close();
		
		//录制完成,切换replay状态
		control.replay();
		
		//调用实际的方法
		String res = login.login(conn, name, pas);
		String expected = "登陆成功。";
		assertEquals(expected, res);
		
		//验证
		control.verify();
	
	}

}

2、重要的概念

在一个完整的测试过程中,一个Mock对象将会经历两个状态:Record状态和Replay状态。Mock对象一经创建,它的状态就被置为Record。在Record状态,用户可以设定Mock对象的预期行为和输出,这些对象行为被录制下来,保存在Mock对象中。

将Mock对象切换到Replay状态

在使用Mock对象进行实际的测试前,我们需要将Mock对象的状态切换为Replay。在Replay状态,Mock对象能够根据设定对特定的方法调用作出预期的响应。将Mock对象切换成Replay状态有两种方式,您需要根据Mock对象的生成方式进行选择。如果Mock对象是通过org.easymock.EasyMock类提供的静态方法createMock生成的(第1节中介绍的第一种Mock对象生成方法),那么EasyMock类提供了相应的replay方法用于将Mock对象切换为Replay状态:

replay(mockResultSet);

如果Mock对象是通过IMocksControl接口提供的createMock方法生成的(第1节中介绍的第二种Mock对象生成方法),那么您依旧可以通过IMocksControl接口对它所创建的所有Mock对象进行切换:

control.replay();

对Mock对象的行为进行验证

在利用Mock对象进行实际的测试过程之后,我们还有一件事情没有做:对Mock对象的方法调用的次数进行验证。

为了验证指定的方法调用真的完成了,我们需要调用verify方法进行验证。和replay方法类似,您需要根据Mock对象的生成方式来选用不同的验证方式。如果Mock对象是由org.easymock.EasyMock类提供的createMock静态方法生成的,那么我们同样采用EasyMock类的静态方法verify进行验证:

verify(mockResultSet);

如果Mock对象是有IMocksControl接口所提供的createMock方法生成的,那么采用该接口提供的verify方法,例如第1节中的IMocksControl实例control:

control.verify();

Mock对象的重用

为了避免生成过多的Mock对象,EasyMock允许对原有Mock对象进行重用。要对Mock对象重新初始化,我们可以采用reset方法。和replay和verify方法类似,EasyMock提供了两种reset方式:(1)如果Mock对象是由org.easymock.EasyMock类中的静态方法createMock生成的,那么该Mock对象的可以用EasyMock类的静态方法reset重新初始化;(2)如果Mock方法是由IMocksControl实例的createMock方法生成的,那么该IMocksControl实例方法reset的调用将会把所有该实例创建的Mock对象重新初始化。

在重新初始化之后,Mock对象的状态将被置为Record状态。

参考:1、http://www.ibm.com/developerworks/cn/opensource/os-cn-easymock/(推荐)

      2、http://macrochen.iteye.com/blog/298032

相关推荐