`

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 的使用方法简介

    easymock 的使用方法简介easymock 的使用方法简介

    easymock的使用,含demo

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

    EasyMock 使用案例(含lib)

    使用EasyMock做java单元测试的例子,包含所需要的jar包

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

    easymock2 EasyMock使用简明手册

    EasyMock 使用方法与原理剖析

    EasyMock单元测试的扩展; EasyMock简介(抽象类接口做测试); EasyMock来进行测试; EasyMock如何打桩;...EasyMock使用技巧; EasyMock使用简明手册; EasyMock使用说明; EasyMock使用手记; 用Mock object进行隔离测试;

    easyMock

    easyMock

    EasyMock介绍和使用

    IBM网站对EasyMock和使用场景的一些介绍

    EasyMock 3.1相关jar(所有)

    还在为EasyMock使用时出异常而烦恼? 本压缩包包含除了Junit4之外easyMock3.1所用到的所有相关jar包,junit4可自己导入eclipse自带的即可 本压缩包包括: asm.jar cglib.jar objenesis.jar等 其中asm与cglib已兼容,放心...

    模拟测试辅助工具easyMock.zip

    EasyMock 是一套通过简单的方法对于指定的接口或类生成 Mock 对象的类库,它能利用对接口或类的模拟来辅助单元测试。 Mock 方法是单元测试中常见的一种技术,它的主要作用是模拟一些在应用中不容易构造或者比较...

    easyMock2.2.doc

    easyMock2.2

    EasyMock 教程

    EasyMock使用教程,快来看看你还有什么秘密没有发现吧!

    easymock-3.2.jar

    EasyMock主要是为测试提供模拟数据,比如你可以模拟HttpServletRequest。

    EasyMock

    NULL 博文链接:https://bruceliu02.iteye.com/blog/1775446

    EasyMock 使用方法与原理剖析.rar

    EasyMock 使用方EEasyMock 使用方法与原理剖析.rar

    easymock测试servlet

    easymock测试servlet使用代码

    easymock.jar,easymockclassextension.jar

    还在为找不到jar文件烦心吗,不用了到我空间来有你想要的,持续更新。。。 easymock.jar,easymockclassextension.jar

    EasyMock与Mockito 使用

    NULL 博文链接:https://zhangzhenting.iteye.com/blog/1829416

    EasyMock 实例

    EasyMock 的文档还有简单实例 还有需要的jar包

    easymock-4.2.jar

    EasyMock 是一套通过简单的方法对于指定的接口或类生成 Mock 对象的类库,它能利用对接口或类的模拟来辅助单元测试。 Mock 方法是单元测试中常见的一种技术,它的主要作用是模拟一些在应用中不容易构造或者比较复杂...

Global site tag (gtag.js) - Google Analytics