您的位置:首页 > 其它

Easymock之初见

2014-01-12 20:54 246 查看
准本工作:

从easymock3版本之后,可以同时mock接口和类,不再需要extention class 包了。使用easymock需要依赖两个包,分别是 ObjenesisCglib

基本概念:

一 . mock和stub的相同点和不同点?

在Manning Junit in Action一书中是这样描述的:

Mocks replace the objects with which your methods
under test collaborate, offering a layer of isolation. In that sense, they’re similar to stubs. But
this is where the similarity ends, because mocks don’t implement any logic: they’re empty shells that provide methods to let the tests control
the behavior of all the business methods of the faked class.

详细的来讲

1.相同点:mock和stub都可以用来对系统(或者将粒度放小为模块,单元)进行隔离。

2.不同点:待补充


Lifecycle

Test lifecycle with stubs:

Setup - Prepare object that is being tested and its stubs collaborators.

Exercise - Test the functionality.

Verify state - Use asserts to check object's state.

Teardown - Clean up resources.

Test lifecycle with mocks:

Setup data - Prepare object that is being tested.

Setup expectations - Prepare expectations in mock that is being used by primary object.

Exercise - Test the functionality.

Verify expectations - Verify that correct methods has been invoked in mock.

Verify state - Use asserts to check object's state.

Teardown - Clean up resources.

三.easymock的基本用法

mock一般都有三个阶段,分别是 record,replay,verify。即首先记录mock对象上的操作,然后重演这些操作,最后验证这些操作。

在mock对象调用replay()方法之前是记录mock上的操作阶段。在调用replay()方法之后,才表现出mock对象的行为,并检查这些期望的操作是否真正的被调用。

要获得一个Mock对象,需要三个步骤:

使用接口创建一个mock对象
记录期望的行为(record the expected behavior)
将mock对象切换到replay状态,重演期望的行为

下面使用一个最常用的例子来展示一下mock的基本用法:

实体类User,DAO层接口UserDao,Service层接口UserService,测试对象Service的各个方法是否正确,service所需依赖UserDao,所以需要mock出UserDao对象,用来隔离层,专注于service层的单元测试。类图如下:





User对象:

public class User {
private int id;
private String name;
private String age;
public User(){}
public User(int id,String name,String age){
this.id=id;
this.name=name;
this.age=age;
}
//省略getter and setter方法
public void say(){
System.out.println(String.format("%d %s %s ",id,name,age));
}
}


UserDao接口:

public interface UserDao {
User getUserById(int id);
int count();
public String getUserAddress() throws Exception;
}


UserService类,注意这里为了简单,没有使用接口,而是直接使用类代替

public class UserService {
private UserDao userDao;

public UserDao getUserDao() {
return userDao;
}

public void setUserDao(UserDao userDao) {
this.userDao = userDao;
}

public String getUserNameById(int id){
String username=userDao.getUserById(id).getName();
return username;
}

public int count(){
return userDao.count();
}
public User getUser(int id){
return userDao.getUserById(id);
}
public String getUserAddress(int id) throws Exception{
return userDao.getUserAddress();
}
}
接下来是主要的测试代码:

package easymock;

import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;

import static org.easymock.EasyMock.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;

/**
* Created by superman on 14-1-12.
*/
public class UserServiceTest {
private UserService userService;
private UserDao userDaoMock;
private User user;
@Before
public void setUp(){
user=new User(1,"tom","20");
userService=new UserService();
userDaoMock=createMock(UserDao.class);
}
@Test
public void testGetNameById(){
expect(userDaoMock.getUserById(1)).andReturn(user);
replay(userDaoMock);

userService.setUserDao(userDaoMock);

String name=userService.getUserNameById(1);
assertEquals("tom",name);
verify(userDaoMock);
}
@Test
public void testRepeateCall(){
expect(userDaoMock.getUserById(1)).andReturn(user).times(2);
replay(userDaoMock);
userService.setUserDao(userDaoMock);

String name=userService.getUserNameById(1);
name=userService.getUserNameById(1);
verify(userDaoMock);
assertEquals("tom",name);
}
@Test
public void testReturnValue(){
//        expect(userDaoMock.getUserById(1)).andReturn(user);
userDaoMock.getUserById(lt(2));
expectLastCall().andReturn(user);

replay(userDaoMock);
userService.setUserDao(userDaoMock);
User user=userService.getUser(1);
assertNotNull(user);
verify(userDaoMock);
}
@Test
@Ignore
public void testException(){
try {
expect(userDaoMock.getUserAddress()).andThrow(new Exception("no address attribute"));
replay(userDaoMock);
userService.setUserDao(userDaoMock);
userService.getUserAddress(1);
verify(userDaoMock);
} catch (Exception e) {
e.printStackTrace();
}
}
}


Tip:mock创建的构造方法

createMock(String name, Class claz);

createMock(Class claz);

如果使用第二种,如果测试结果没有预期的,那么会出现如下提示:

java.lang.AssertionError:
Expectation failure on verify:
read(): expected: 7, actual: 0

如果使用第一种,则会出现如下提示:

java.lang.AssertionError:
Expectation failure on verify:
name.read(): expected: 7, actual: 0

红色部分是区别,所以使用第一种更好,标注了提示。

测试代码主要参考:http://easymock.org/EasyMock3_0_Documentation.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: