`

EasyMock的简单使用(摘)

    博客分类:
  • java
阅读更多

xp开发的一个利器--EasyMock。
EasyMock是一种 动态生成模仿对象以便应用于单元测试的工具,有了它可摆脱容器进行单元测试了。
它的使用很简单,下面一个简单登陆验证的例子:
public   class  LoginServlet  extends  HttpServlet {


protected   void  doPost(HttpServletRequest request, HttpServletResponse response)  throws  ServletException, IOException {

String username 
=  request.getParameter( " username " );

String password 
=  request.getParameter( " password " );

//  check username & password:

if ( " admin " .equals(username)  &&   " 123456 " .equals(password)) {
     ServletContext context 
=  getServletContext();
     RequestDispatcher dispatcher 
=  context.getNamedDispatcher( " dispatcher " );
     dispatcher.forward(request, response);
}
else  {
     
throw   new  RuntimeException( " Login failed. " );
}
}
}

这个 Servlet 实现简单的用户验证的功能,若用户名和口令匹配“ admin ”和“ 123456 ”,则请求被转发到指定的 dispatcher 上,否则,直接抛出 RuntimeException

为了测试 doPost() 方法,我们需要模拟 HttpServletRequest ServletContext RequestDispatcher 对象,以便脱离 J2EE 容器来测试这个 Servlet

我们建立 TestCase ,名为 LoginServletTest

public   class  LoginServletTest  extends  TestCase {

}

我们首先测试当用户名和口令验证失败的情形,演示如何使用EasyMock来模拟HttpServletRequest对象:

public   void  testLoginFailed()  throws  Exception {

MockControl mc 
=  MockControl.createControl(HttpServletRequest. class );

HttpServletRequest request 
=  (HttpServletRequest)mc.getMock();

//  set Mock Object behavior:

request.getParameter(
" username " );

mc.setReturnValue(
" admin " 1 );

request.getParameter(
" password " );

mc.setReturnValue(
" 1234 " 1 );

//  ok, all behaviors are set!

mc.replay();

//  now start test:

LoginServlet servlet 
=   new  LoginServlet();

try  {

servlet.doPost(request, 
null );

fail(
" Not caught exception! " );

}

catch (RuntimeException re) {

assertEquals(
" Login failed. " , re.getMessage());

}

//  verify:

mc.verify();

}

仔细观察测试代码,使用 EasyMock 来创建一个 Mock 对象需要首先创建一个 MockControl
MockControl mc  =  MockControl.createControl(HttpServletRequest. class );

然后,即可获得 MockControl 创建的 Mock 对象:
HttpServletRequest request  =  (HttpServletRequest)mc.getMock();

下一步,我们需要“录制” Mock 对象的预期行为。在 LoginServlet 中,先后调用了 request.getParameter("username") request.getParameter("password") 两个方法,因此,需要在 MockControl 中设置这两次调用后的指定返回值。我们期望返回的值为“ admin ”和“ 1234 ”:
request.getParameter( " username " );  //  期望下面的测试将调用此方法,参数为"username"
mc.setReturnValue( " admin " 1 );  //  期望返回值为"admin",仅调用1次

request.getParameter(
" password " );  //  期望下面的测试将调用此方法,参数为" password"

mc.setReturnValue(
" 1234 " 1 );  //  期望返回值为"1234",仅调用1次
紧接着,调用 mc.replay() ,表示 Mock 对象“录制”完毕,可以开始按照我们设定的方式运行,我们对 LoginServlet 进行测试,并预期会产生一个 RuntimeException
LoginServlet servlet  =   new  LoginServlet();

try  {

servlet.doPost(request, 
null );

fail(
" Not caught exception! " );

}

catch (RuntimeException re) {

assertEquals(
" Login failed. " , re.getMessage());

}

由于本次测试的目的是检查当用户名和口令验证失败后, LoginServlet 是否会抛出 RuntimeException ,因此, response 对象对测试没有影响,我们不需要模拟它,仅仅传入 null 即可。

最后,调用 mc.verify() 检查 Mock 对象是否按照预期的方法调用正常运行了。

运行 JUnit ,测试通过!表示我们的 Mock 对象正确工作了!
  下一步,我们来测试当用户名和口令匹配时,LoginServlet应当把请求转发给指定的RequestDispatcher。在这个测试用例中,我们除了需要HttpServletRequest Mock对象外,还需要模拟ServletContextRequestDispatcher对象:


MockControl requestCtrl  =  MockControl.createControl(HttpServletRequest. class );

HttpServletRequest requestObj 
=  (HttpServletRequest)requestCtrl.getMock();

MockControl contextCtrl 
=  MockControl.createControl(ServletContext. class );

final  ServletContext contextObj  =  (ServletContext)contextCtrl.getMock();

MockControl dispatcherCtrl 
=  MockControl.createControl(RequestDispatcher. class );

RequestDispatcher dispatcherObj 
=  (RequestDispatcher)dispatcherCtrl.getMock();

按照doPost()的语句顺序,我们设定Mock对象指定的行为:

requestObj.getParameter(
" username " );

requestCtrl.setReturnValue(
" admin " 1 );

requestObj.getParameter(
" password " );

requestCtrl.setReturnValue(
" 123456 " 1 );

contextObj.getNamedDispatcher(
" dispatcher " );

contextCtrl.setReturnValue(dispatcherObj, 
1 );

dispatcherObj.forward(requestObj, 
null );

dispatcherCtrl.setVoidCallable(
1 );

requestCtrl.replay();

contextCtrl.replay();

dispatcherCtrl.replay();

然后,测试 doPost() 方法,这里,为了让 getServletContext() 方法返回我们创建的 ServletContext Mock 对象,我们定义一个匿名类并覆写 getServletContext() 方法:
LoginServlet servlet  =   new  LoginServlet() {

public  ServletContext getServletContext() {

return  contextObj;

}

};

servlet.doPost(requestObj, 
null );

最后,检查所有Mock对象的状态:

requestCtrl.verify();

contextCtrl.verify();

dispatcherCtrl.verify();

运行 JUnit ,测试通过!

倘若 LoginServlet 的代码有误,例如,将 context.getNamedDispatcher("dispatcher") 误写为 context.getNamedDispatcher("dispatcher2") ,则测试失败, JUnit 报告:

junit.framework.AssertionFailedError:

Unexpected method call getNamedDispatcher("dispatcher2"):

getNamedDispatcher("dispatcher2"): expected: 0, actual: 1

getNamedDispatcher("dispatcher"): expected: 1, actual: 0

at ...

总结:

虽然 EasyMock 可以用来模仿依赖对象,但是,它只能动态模仿接口,无法模仿具体类。这一限制正好要求我们遵循“针对接口编程”的原则:如果不针对接口,则测试难于进行。应当把单元测试看作是运行时代码的最好运用,如果代码在单元测试中难于应用,则它在真实环境中也将难于应用。总之,创建尽可能容易测试的代码就是创建高质量的代码。

  现在,easymock可以模仿类了,以下是在springside摘的:

// 设定BookManager MockObject
        bookManagerMockControl  =  MockClassControl.createControl(BookManager. class );
        bookManagerMock 
=  (BookManager) bookManagerMockControl.getMock();
        controller.setBookManager(bookManagerMock);
       
// 录制getAllBook()和getCategorys方法的期望值
        bookManagerMock.getAllBook();
        bookManagerMockControl.setReturnValue(
new  ArrayList());
        bookManagerMockControl.replay();
        
// 执行操作
        mv  =  controller.handleRequest(request, response);
// 验证结果         
        assertModelAttributeAvailable(mv,  " books " );


分享到:
评论

相关推荐

    EasyMock 使用案例(含lib)

    在这个"EasyMock 使用案例(含lib)"中,我们将会深入探讨如何利用EasyMock进行Java单元测试,并通过具体的例子——EasyMockDemo来讲解其用法。 首先,EasyMock的基本理念是让你能够定义模拟对象的行为,比如它应该...

    EasyMock介绍和使用

    【EasyMock的使用场景】 EasyMock适用于以下几种情况: 1. **依赖隔离**:当被测试类依赖于其他复杂或难以配置的外部服务或资源时,EasyMock可以通过模拟这些依赖,使测试环境更加可控。 2. **测试驱动开发(TDD...

    easymock的使用,含demo

    EasyMock 是一套通过简单的方法对于指定的接口或类生成 Mock 对象的类库,它能利用对接口或类的模拟来辅助单元测试。本文将对 EasyMock 的功能和原理进行介绍,并通过示例来说明如何使用 EasyMock 进行单元测试。 ...

    easymock2.4+EasyMock使用简明手册.pdf

    EasyMock是Java编程中的一款强大的模拟框架,它允许开发者在单元测试中创建和控制...通过阅读《EasyMock使用简明手册》和解压后的easymock2.4.zip文件,开发者可以深入理解并掌握如何有效地使用EasyMock进行单元测试。

    EasyMock

    在实际使用EasyMock时,我们通常会遵循以下步骤: 1. **创建模拟对象**:首先,你需要通过`EasyMock.createMock()`方法创建一个模拟对象。例如,如果你有一个名为`MyInterface`的接口,你可以这样创建它的模拟对象...

    easyMock

    EasyMock适合简单的模拟场景,而Mockito提供了更丰富的功能和更简洁的API。PowerMock则可以模拟静态方法、构造函数等不易模拟的元素。 总的来说,EasyMock是Java单元测试中的一个重要工具,通过模拟对象和设置预期...

    EasyMock与Mockito 使用

    - EasyMock适合简单的模拟需求,API相对简单,但功能相对有限。 - Mockito则提供更强大的功能,如验证、顺序验证等,适用于复杂的测试场景,但学习曲线可能稍陡峭。 在实际使用中,可以根据项目需求和团队偏好选择...

    EasyMock 使用方法与原理剖析

    为了更好地理解EasyMock的使用,下面是一个简单的例子: ```java @Test public void testMyCode() { MyClass mock = EasyMock.createMock(MyClass.class); EasyMock.expect(mock.myMethod()).andReturn("mocked ...

    easymock.jar,easymockclassextension.jar

    2. **创建模拟对象**:使用Easymock的`createMock`或`createNiceMock`方法创建模拟对象。 3. **设置预期**:通过`expect`方法设定模拟对象的方法调用预期。 4. **启动测试**:调用`replay`方法开始执行模拟。 5. ...

    easymock-3.2.zip

    3. **示例文档**:这些示例通常是一些简单的代码片段,展示了如何在实际项目中应用EasyMock。它们可以作为起点,帮助初学者快速上手。 4. **所需jar包**:这是EasyMock运行所需的库文件。在Java项目中,你需要将...

    EasyMock的安装与部署所需全部文件.zip

    为了部署和使用EasyMock,你需要将源码导入一个支持Java开发的IDE(如Eclipse或IntelliJ IDEA),然后按照提供的说明进行编译和配置。 在部署流程中,一般步骤如下: 1. 安装Node.js:访问官网下载Windows安装包,...

    EasyMock 简介

    EasyMock 是一套用于通过简单的方法对于给定的接口生成 Mock 对象的类库,旨在解决单元测试中的 Mock 对象构建问题。以下是 EasyMock 的详细介绍: 单元测试与 Mock 方法 单元测试是对应用中的某一个模块的功能...

    easymock资料和源代码实例

    在压缩包中的"easymock"文件中,可能包含了Easymock的使用教程、源代码示例和相关文档,这些都是深入理解和学习Easymock的好资源。通过阅读这些材料,你可以更好地掌握如何在实际项目中运用Easymock进行单元测试,...

    EasyMock 实例

    5. **验证行为**:测试完成后,使用`EasyMock.verify()`方法检查模拟对象是否按照预期被调用了。这有助于确保你的代码正确地使用了模拟对象。 ```java EasyMock.verify(myServiceMock); ``` 6. **清理资源**:...

    Learning EasyMock3.0 By Official Example

    例如,使用 `EasyMock.expect()` 方法设定预期,然后调用 `EasyMock.replay()` 准备测试,最后使用 `EasyMock.verify()` 进行验证。 3. `EndecaConceptsGuide.pdf`:Endeca 是一个数据管理平台,这个指南可能涉及到...

    easymock.jar包

    Easymock是一个开源项目,它的主要目标是提供一种简单的方式来创建和控制模拟对象。通过模拟对象,我们可以在不依赖实际环境的情况下测试代码,这在单元测试中尤其有用,因为我们可以精确地控制测试条件,避免了外部...

Global site tag (gtag.js) - Google Analytics