`
zl198751
  • 浏览: 278427 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Spring Mock

阅读更多

文章节选自:

http://lanmh.iteye.com/blog/207500

http://static.springsource.org/spring/docs/2.5.x/reference/testing.html

 

 

Spring 的 mock 组建主要分3部分:

1. JNDI
The org.springframework.mock.jndi package contains an implementation of the JNDI SPI, which is useful for setting up a simple JNDI environment for test suites or stand-alone applications. If, for example, JDBC DataSources get bound to the same JNDI names in test code as within a J2EE container, both application code and configuration can be reused in testing scenarios without modification.
2. Servlet API
The org.springframework.mock.web package contains a comprehensive set of Servlet API mock objects, targeted at usage with Spring's Web MVC framework, which are useful for testing web contexts and controllers. These mock objects are generally more convenient to use than dynamic mock objects (e.g., EasyMock) or existing Servlet API mock objects (e.g., MockObjects).
3. Portlet API
The org.springframework.mock.web.portlet package contains a set of Portlet API mock objects, targeted at usage with Spring's Portlet MVC framework.

 

项目中主要用到的是2. Servelt API(org.springframework.mock.web),可以方便的mock出httprequest,httpsession等对象。

 

Spring Mock类简介

Mock对象是一个术语,原来主要流行于eXtreme程序员和JUnit小组中。在单元测 试上下文中,一个mock对象是指这样的一个对象——它能够用一些“虚构的占位符”功能来“模拟”实现一些对象接口。在测试过程中,这些虚构的占位符对象 可用简单方式来模仿对于一个组件的期望的行为和结果,从而让你专注于组件本身的彻底测试而不用担心其它依赖性问题。

Spring从J2EE的Web端为每个关键接口提供了一个mock实现:

MockHttpServletRequest—几乎每个单元测试中都要使用这个类,它是J2EE Web应用程序最常用的接口HttpServletRequest的mock实现。

MockHttpServletResponse—此对象用于HttpServletResponse接口的mock实现。

MockHttpSession—这是另外一个经常使用的mock对象(后文将讨论此类在会话绑定处理中的应用)。

DelegatingServletInputStream—这个对象用于ServletInputStream接口的mock实现。

DelegatingServletOutputStream—这个对象将代理ServletOutputStream实现。在需要拦截和分析写向一个输出流的内容时,你可以使用它。

总之,在实现你自己的测试控制器时,上面这些对象是最为有用的。然而,Spring也提供了下列相应于其它不太常用的组件的mock实现(如果你是一个底层API开发者,那么你可能会找到其各自的相应用法):

MockExpressionEvaluator—这个mock对象主要应用于你想开发并测试你自己的基于JSTL的标签库时。

MockFilterConfig—这是FilterConfig接口的一个mock实现。

MockPageContext—这是JSP PageContext接口的一个mock实现。你会发现这个对象的使用有利于测试预编译的JSP。

MockRequestDispatcher—RequestDispatcher接口的一个mock实现,你主要在其它mock对象内使用它。

MockServletConfig—这是ServletConfig接口的一个mock实 现。在单元测试某种Web组件(例如Struts框架所提供的Web组件)时,要求你设置由MockServletContext所实现的 ServletConfig和ServletContext接口。

那么,我们该如何使用这些mock对象呢?我们知道,HttpServletRequest 是一个持有描述HTTP参数的固定值的组件,而正是这些参数驱动Web组件的功能。MockHttpServletRequest,作为 HttpServletRequest接口的一个实现,允许你设置这些不可改变的参数。在典型的Web组件测试情形下,你可以实例化这个对象并按如下方式 设置其中的任何参数:

//指定表单方法和表单行为

MockHttpServletRequest request = new MockHttpServletRequest("GET", "/main.app");

request.addParameter("choice", expanded);request.addParameter("contextMenu", "left");

同样地,你可以实例化并全面地控制和分析HttpResponse和HttpSession对象。接下来,让我们简要观察Spring所提供的特定的JUnit框架扩展。

二、普通Web测试情形

在此,我们将回顾测试Web组件的普通情形以及怎样在其中使用Spring的mock对象和JUnit框架扩展。

(一)确定一个正确的视图

基于输入参数生成正确的视图可能是在操作一个Web应用程序时最普通的功能。在Spring MVC的上下文中,这意味着Spring MVC将基于参数的状态返回某种ModelAndView对象。你可以通过简单地利用如下的Mock对象以一个常规JUnit测试方式来测试这项功能:

public void final testGettingToDetails throws Exception{

MyController myController = new MyController(); myController.setDetailsView( detailsViewName );

MockHttpServletRequest request = new MockHttpServletRequest();

MockHttpServletResponse response = new MockHttpServletResponse();

request.setMethod("POST");

request.addParameter("viewDetails", "true");

ModelAndView modelAndView = myController.handleRequest(request, response);

assertEquals("Incorrect view name", detailsViewName,modelAndView.getViewName());

}

既然控制器很可能会利用一些服务对象来决定结果视图,那么你还可以定制控制器中所用的这些mock服务对象。关于利用定制对象的更多资料,请参考mockobjects.com。

(二)会话相关的操作

对于任何J2EE Web应用程序来说,另一个必须实现的操作是HttpSession绑定处理。例如,Spring MVC可能需要决定是否一个对象处于会话中及其具体状态以便产生正确的结果。你可以利用MockHttpSession对象和JUnit框架测试这种情 形。请参考如下的代码片断:

public void testInvokesCorrectMethodWithSession() throws Exception {

TestController cont = new TestController();

MockHttpServletRequest request = new MockHttpServletRequest("GET", "/invoiceView.app");

request.setSession(new MockHttpSession(null));

HttpServletResponse response = new MockHttpServletResponse();

ModelAndView mv = cont.handleRequest(request, response);

assertTrue("Invoked loggedIn method", cont.wasInvoked("loggedIn"));

assertTrue("view name is ",mv.getViewName().equals("loggedIn"));

assertTrue("Only one method invoked", cont.getInvokedMethods() == 1);//测试控制器但是不使用会话

request = new MockHttpServletRequest("GET", "/invoiceView.app");

response = new MockHttpServletResponse();

try {

cont.handleRequest(request, response);

fail("Should have rejected request without session");

} catch (ServletException ex) {//在此加入期盼的异常处理}}

(三)转发和重定向

一个Spring MVC组件执行的操作能够导致转发或重定向到另一个URL。如果你的目标是分析转发或重定向的结果,那么你可以测试这一情形—通过分析MockHttpResponse对象并进而确定有哪些内容包含在它的重定向或转发值中,如下所示:

String responseString = ((MockHttpServletResponse)httpResponse).getForwardedUrl();

assertEquals( "Did not forward to the expected URL", responseString, expectedString);

三、生成正确的二进制输出

如何确定你有多少次必须实现“View as PDF”这一功能?下面的JUnit代码片断使用mock输出流对象实现这一功能的正确测试:

public void testPDFGeneration() throws Exception {

MockHttpServletRequest request = new MockHttpServletRequest();

MockHttpServletResponse response = new MockHttpServletResponse();

viewInvoiceAsPDFController.handleRequest( request, response );

byte[] responsePDFValues = response.getContentAsByteArray();

byte[] expectedPDFValues = loadBytesFromTestFile();

assertTrue( "Did not generate expected PDF content.", Arrays.equals(responsePDFValues,expectedPDFValues ));

}

注意,在此你的控制器ViewInvoiceAsPDFController不是返回ModelAndView对象,而是产生了二进制输出—你可以使用一个二进制的数组形式来捕获此控制器并对此进行正确性评价。

四、事务性单元测试

到目前为止,你已看到了相对简单的JUnit测试—它仅发生在用mock对象支持的一个控制 器的上下文中。但是,如果测试一个Web组件只有在一个事务性上下文(例如,通过依赖性注入与Hibernate集成到一起)中才有意义的情况又会怎么样 呢?不必担心,Spring MVC为JUnit框架提供了一个体面的扩展集合—它能准确地提供依赖性注入和事务安全测试(也就是,任何更新在测试完成后都将被回滚)。

测试步骤:

让我们看一种假想的情形—你要实现一个组件(例如MyTransactionalController)测试,该组件运行在一个事务性的上下文中(也即,其方法调用的结果发生在一个事务内并且它应该在测试运行完后被回滚):

1.创建一个定制的JUnit类(MyTransactionalControllerTest),它扩展了Spring的JUnit扩展类 AbstractTransactionalSpringContextTests:

import org.springframework.test.AbstractDependencyInjectionSpringContextTests;

public class MyTransactualControllerTest extends AbstractTransactionalSpringContextTests {

public class.

2.为了实现从Spring内置的单元测试中发现Spring管理的bean,你需要重载getConfigLocations()方法并且返回上下文文件位置的String数组,请看如下:

protected abstract String[] getConfigLocations(){ return new String[] {"classpath:/test/spring-context.xml"};}

3.拥有该类的一个测试属性及其相关联的getter和setter。由于 AbstractTransactionalSpringContextTests利用了auto-wiring(这是Spring框架的一个特性—能够 根据类属性的名字识别类依赖性并且用Spring bean填入相匹配的名字或ID)技术而且在测试时它将自动地解决类的依赖性问题,所以在Spring上下文文件中该类属性具有与Spring管理的 bean一样的名字并且在测试时每个属性都有一个适当命名的setter:

public MyTransactualController myTransactualController;

/** * @返回myTransactualController。 */

public MyTransactualController getMyTransactualController()

{

return this.myTransactualController;

}

/** *@参数myTransactualController。 */public void setMyTransactualController( MyTransactualController myTransactualController) { this.myTransactualController = myTransactualController;

}

4.就象你通常操作“普通的”JUnit测试一样实现测试方法:

public void testCorrectBehavior() throws Exception{ //运行该事务性方法 myTransactualController.submitPayment( new Payment( 100 ) );

assertTrue( myTransactualController.isValid() );}

注意,你是在调用可能会更新数据库的方法submitPayment。Spring的JUnit扩展(AbstractTransactionalSpringContextTests)将在这个测试方法结束后实现自动回滚。

5.如果你需要执行任何安装或清除任务,则可以重载 AbstractTransactionalSpringContextTests的onSetUpBeforeTransaction()或 onSetUpInTransaction()方法。AbstractTransactionalSpringContextTests将重载从 TestCase继承来的setUp()和tearDown()方法并且使其成为final类型。


分享到:
评论

相关推荐

    java单元测试 spring mock的使用

    "Java单元测试Spring Mock的使用" 在Java Web应用中,单元测试是非常重要的一步,它可以帮助开发者检测代码的正确性和可靠性。传统的单元测试方法需要部署到容器中,然而,这种方法存在一些缺陷,例如需要长时间的...

    spring-mock.jar

    《深入解析Spring Mock框架》 在Java开发领域,Spring框架以其强大的功能和灵活性深受开发者喜爱。而Spring Mock作为Spring框架的一个重要组成部分,为测试提供了强大的模拟(mocking)能力,帮助开发者在不依赖...

    spring-mock-2.0-rc3.jar

    Spring针对J2EE的常用Web接口提供了Mock,这些组件被发布于spring-mock.jar,介绍如下: MockHttpServletRequest:HttpServletRequest接口的mock实现。 MockHttpServletResponse:HttpServletResponse接口的mock...

    struts-junit spring-mock spring-test junit的javadoc.jar文档

    struts-junit spring-mock spring-test junit等的javadoc.jar格式的API文档,直接导入Eclipse/MyEclipse/Netbeans等IDE即可实现快速API查询。 包含以下文件: File name -------------------------------------- ...

    java8看不到源码-springmock:替代spring模拟基础设施

    @MockBean,但允许您使用由您选择的库创建的模拟。 内容 特征 将 spock/mockito 创建的模拟注入测试用例 (, ) 扩展模拟和间谍配置 (, ) 在 spring 上下文中注册在配置/测试类上声明的模拟(只需将 @AutowiredMock @...

    spring-mock-2.0.8.jar

    spring-mock-2.0.8.jar

    spring-data-mock:用于Spring数据存储库的Mock工具

    Spring数据模拟 这是一个相当灵活的通用框架,用于模拟Spring Data存储库。 Spring Data为将管理数据库及其随后产生的查询与业务层的查询分开来提供了很好的基础。 这对于编写服务非常有用。 他们只需要依靠Spring...

    022-preload-database-execute-sql-spring-testing

    Spring提供了Mockito和Spring Mock等工具,可以模拟数据库访问层的行为。 9. **Spring Boot Testing**:如果项目是基于Spring Boot的,那么测试支持会更加方便。Spring Boot通过`spring-boot-starter-test`模块集成...

    JavaEE源代码 spring-mock

    JavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源代码 spring-mockJavaEE源...

    spring-mock-2.0.3.jar

    spring-mock-2.0.3.jar

    mock

    本文将深入探讨Mock的概念及其在Struts2与Spring框架中的应用,同时也会涉及到JUnit和EasyMock等单元测试工具。 Mock技术的核心是创建虚拟对象,这些对象的行为可以被精确地控制,从而模拟真实系统中的协作对象。在...

    单元测试

    在描述中提到的"spring-mock-2.0.8.jar",这可能是指Spring框架的一个版本,其中包含模拟对象(mock objects)的工具,用于在单元测试中替代真实的依赖项。Spring Mock库允许开发者在不启动完整Spring应用上下文的...

    Spring Boot与MyBatis结合 实现对mock平台改造

    本篇将详细讲解如何使用Spring Boot与MyBatis框架结合,对Mock平台进行改造。 首先,Spring Boot是基于Spring框架的简化版本,它内置了各种常用组件,如Tomcat服务器、自动配置功能等,大大简化了Java Web应用的...

    Struts2核心jar包(2)

    10. **spring-mock.jar**:Spring Mock库用于模拟Spring框架中的对象,便于在不依赖实际环境的情况下进行单元测试。 这些库组合在一起,构成了一个强大的开发环境,支持开发人员构建功能丰富的、可维护的Struts2...

Global site tag (gtag.js) - Google Analytics