Easymock之初见

准本工作:
  从easymock3版本之后,可以同时mock接口和类,不再需要extention class 包了。 使用easymock需要依赖两个包,分别是  Objenesis  和  Cglib 
基本概念:
一 .  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:

  1. Setup - Prepare object that is being tested and its stubs collaborators.
  2. Exercise - Test the functionality.
  3. Verify state - Use asserts to check object's state.
  4. Teardown - Clean up resources.

Test lifecycle with mocks:

  1. Setup data - Prepare object that is being tested.
  2. Setup expectations - Prepare expectations in mock that is being used by primary object.
  3. Exercise - Test the functionality.
  4. Verify expectations - Verify that correct methods has been invoked in mock.
  5. Verify state - Use asserts to check object's state.
  6. Teardown - Clean up resources.
三.easymock的基本用法
          mock一般都有三个阶段,分别是 record,replay,verify。即首先记录mock对象上的操作,然后重演这些操作,最后验证这些操作。
在mock对象调用replay()方法之前是记录mock上的操作阶段。在调用replay()方法之后,才表现出mock对象的行为,并检查这些期望的操作是否真正的被调用。
要获得一个Mock对象,需要三个步骤:
  1. 使用接口创建一个mock对象
  2. 记录期望的行为(record the expected behavior)
  3. 将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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值