📚 开源资源分享——颜佐光的个人书架
✉️ 联系站长
书架 / 测试 / mock

EasyMock简介和代码示例

2020-03-06 11:10 · 约 5,235 字 · 浏览 2,644 次 · 更新 2020-05-16 22:04mock单元测试
关于EasyMock:

官网:easymock.org

注意:
* 3.0版本前,使用JDK的动态代理实现Mock对象创建,因此只能对接口进行mock,如果需要对类进行mock,需要使用扩展org.easymock.classextension.EasyMock
* 3.0后,可以针对接口&类进行mock

EasyMock范例(Service层代码单元测试):

1.工程中引入EasyMock包:

maven工程的话,pom包中添加依赖:

<dependency>
    <groupId>org.easymock</groupId>
    <artifactId>easymock</artifactId>
    <version>3.4</version>
    <scope>test</scope>
</dependency>

2.被测对象:

public class UserService{
    @Resource
    private UserDao userDao;

    private String getUserName(String userId)
    {
        User user = userDao.select(userId);

        if (null == user)
        {
            return "";
        }else {
            return "offline_" + user.getName();
        }
    }
}

其中UserService依赖UserDao接口的实现

3.测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:CommonUtils.xml")
public class UserServiceTest{

    private UserDao userDaoMock = null;

    private User userMock = null;

    @Resource
    private UserService userService;

    @Before
    public void setUp()
    {
        // 创建mock对象
        userDaoMock = EasyMock.createMock(UserDao.class);
        userMock = EasyMock.createMock(User.class);

        // mock对象注入被测对象
        Field userDaoField = userService.getDeclaredField("userDao");
        userDaoField.setAccessible(true);
        userDaoField.set(userService,userDaoMock);
    }

    @Test
    public void getUserName()
    {
        // 设置mock对象的期望值
        EasyMock.expect(userMock.getName()).andReturn("testName");
        EasyMock.expect(userDaoMock.select("1")).andReturn(userMock);

        // mock对象的replay
        EasyMock.replay(userMock);
        EasyMock.replay(userDaoMock);

        // 断言
        Assert.assertTrue(userService.getUserName("1")
                    .equals("offline_testName"));

        // 验证mock对象是否被调用
        EasyMock.verify(userMock);
        EasyMock.verify(userDaoMock);
    }

    @After
    public void tearDown() throws Exception {
        userDaoMock = null;
        userMock = null;
    }
}

根据官方文档,mock的todolist有:

  • Create the mock
  • Have it set to the tested class
  • Record what we expect the mock to do
  • Tell all mocks we are now doing the actual testing
  • Test
  • Make sure everything that was supposed to be called was called

我们范例中对应是:

1.使用EasyMock生成Mock对象:

userDaoMock = EasyMock.createMock(UserDao.class);
userMock = EasyMock.createMock(User.class);

2.Mock对象注入被测对象:

Field userDaoField = userService.getDeclaredField("userDao");
userDaoField.setAccessible(true);
userDaoField.set(userService,userDaoMock);

3.设定Mock对象的预期行为和输出:

EasyMock.expect(userMock.getName()).andReturn("testName");
EasyMock.expect(userDaoMock.select("1")).andReturn(userMock);

4.将Mock对象切换到Replay状态:

EasyMock.replay(userMock);
EasyMock.replay(userDaoMock);

5.调用Mock对象方法进行单元测试:

Assert.assertTrue(userService.getUserName("1").equals("offline_testName"));

6.确定mock对象有被调用:

EasyMock.verify(userMock);
EasyMock.verify(userDaoMock);
EasyMock进阶:
  • 使用IMocksControl管理多个mock对象
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:CommonUtils.xml")
public class UserServiceTest{

    private IMocksControl iMocksControl = null;

    private UserDao userDaoMock = null;

    private User userMock = null;

    @Resource
    private UserService userService;

    @Before
    public void setUp()
    {
        // 创建mock对象
        iMocksControl = EasyMock.createControl();
        userDaoMock = iMocksControl.createMock(UserDao.class);
        userMock = iMocksControl.createMock(User.class);

        // mock对象注入被测对象
        Field userDaoField = userService.getDeclaredField("userDao");
        userDaoField.setAccessible(true);
        userDaoField.set(userService,userDaoMock);
    }


    @Test
    public void getUserName()
    {
        // 设置mock对象的期望值
        EasyMock.expect(userMock.getName()).andReturn("testName");
        EasyMock.expect(userDaoMock.select("1")).andReturn(userMock);

        // mock对象的replay
        iMocksControl.replay();

        // 断言
        Assert.assertTrue(userService.getUserName("1").equals("offline_testName"));

        // 验证mock对象是否被调用
        iMocksControl.verify();
    }

    @After
    public void tearDown() throws Exception {
        userDaoMock = null;
        userMock = null;
    }
}
  • 使用注解
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = "classpath:CommonUtils.xml")
public class UserServiceTest{
    @Rule
    private EasyMockRule mocks = new EasyMockRule(this);
    private IMocksControl iMocksControl = null;
    @Mock
    private UserDao userDaoMock = null;
    private User userMock = null;
    @TestSubject
    @Resource
    private UserService userService;
    ...
}

解析:

  • 1.mock对象会被注入到userService对象中,@Mock是需要创建的mock对象,@TestSubject是被测类
  • 2.如果没有下面这段代码设置Junit的rule,需要将测试类的Runner设置为@RunWith(EasyMockRunner.class),当你希望使用别的runner类,但是又需要EasyMock的注解时,使用Junit的rule进行扩展
@Rule
private EasyMockRule mocks = new EasyMockRule(this);
← 返回《测试》目录书架 →