博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用spring的mock类进行单元测试
阅读量:4067 次
发布时间:2019-05-25

本文共 6819 字,大约阅读时间需要 22 分钟。

<p>利用spring的mock类进行单元测试: <br>spring框架提供了大量测试的mock类,包括与jndi,porlet,web应用相关的mock类。尤其是web应用相关的mock类,可以大大提高web组件测试的方便性。</p>
<p>打开spring的下载包的mock文件夹(路径...mock/org/springframework/mock/web),就发觉有如下几个文件:</p>
<p><span style="color: #ff0000;">MockHttpServletRequest</span>:是HttpServletRequest接口的mock实现,用来模拟客户端的HTTP请求,很常用的一个类。</p>
<p><span style="color: #ff0000;">MockHttpServletResponse</span>:是HttpServletResponse接口的mock实现,用于模拟服务器对客户端的响应。</p>
<p><span style="color: #ff0000;">MockHttpSession</span>:是对HttpSession接口的mock实现。</p>
<p><span style="color: #ff0000;">DelegatingServletInputStream</span>:是对ServletInputStream接口的mock实现。</p>
<p><span style="color: #ff0000;">DelegatingServletOutputStream</span>:ServletOutputStream的mock实现。需要拦截和分析服务器的输出的流的内容,可以使用该类。</p>
<p>其他的,例如MockFilterConfig,MockPageContext(可以测试预编译的JSP),MockRequestDispatcher,MockServletConfig看名称就知道大概是mock什么的。 <br>举一个例子: <br> MockHttpServletRequest request = new MockHttpServletRequest("POST","/index.do"); <br> request.addParameter("username","name"); <br> request.addParameter("password","word"); </p>
<p><span style="color: #0000ff;"><strong>利用spring来进行集成测试</strong></span>: <br>1、<span style="color: #ff0000;">AbstractSpringContextTests类</span><span style="color: #ff0000;">[1],</span>该类全部方法是protected的,<span style="color: #0000ff;">通常不使用这个类,而使用它的子类们</span>。</p>
<p>2、<span style="color: #ff0000;">AbstractDependencyInjectionSpringContextTests类</span>[2]:<span style="color: #ff0000;">继承于类[1]</span>:名字N长的。如果<span style="color: #0000ff;">仅仅使用Spring依赖注入功能</span>,<span style="color: #0000ff;">可以让测试用例继承该类</span>。</p>
<p>3、<span style="color: #ff0000;">AbstractTransactionalSpringContextTests类[3]:继承于类[2]</span>,继承该类的测试用例在<span style="color: #0000ff;">spring管理的事务中进行,测试完后对数据库的记录不会造成任何影响</span>。<span style="color: #ff00ff;">你对数据库进行一些操作后,它会自动把数据库回滚,这样就保证了你的测试对于环境没有任何影响</span></p>
<p>4、<span style="color: #ff0000;">AbstractTransactionalDataSourceSpringContextTests</span>:<span style="color: #ff0000;">继承于类[3]</span>,功能更强大,<span style="color: #0000ff;">用于测试持久层组件,</span>看其源代码,有一行"protected JdbcTemplate jdbcTemplate;",<span style="color: #0000ff;">提供了一个JdbcTemplate的变量</span>,通过该对象可以直接操作数据库。</p>
<p><a href="http://lighter.javaeye.com/blog/41733">http://lighter.javaeye.com/blog/41733</a>还提供了两个用spring来进行集成测试(对数据库操作进行测试),业务测试(对业务层进行测试)的例子供下载。</p>
<p><span style="font-size: small; color: #ff0000;"><strong>***如何在你的TestCase Class里取得spring context (注意路径问题)?***</strong></span></p>
<p>你的TestCase Class必须继承的是上述四个<span style="color: #ff0000;">AbstractXXXSpringContextTests</span>中的其中一个,那么就<span style="color: #0000ff;">必须实现下面这个方法来取得spring context</span>:</p>
<p> protected abstract String[] <span style="color: #ff0000;">getConfigLocations</span>();</p>
<p>例如:</p>
<p><span style="color: #ff0000;">public String[] getConfigLocations() {<br> String[] configLocations = { "applicationContext.xml","hibernate-context.xml" };<br> return configLocations;<br>}</span></p>
<p><br><span style="font-size: medium; color: #ff00ff;"><strong>请 注意要加载的context xml file的路径问题:上述的代码是基于classpath,因此applicationContext.xml和hibernate- context.xml必须放在classpath里(方法一是把xml files放到WEB-INF/classes目录下,另一种方法就是在project properties里把xml files的路径加到classpath里)</strong></span></p>
<p>那么<span style="font-size: small; color: #ff00ff;"><strong>如果你一定要把context xml files放到WEB-INF目录下,也是可以的,那么应该基于file(基于file的相对路径是相对于project root folder),代码如下:</strong></span></p>
<p><span style="color: #000000;">public String[] getConfigLocations() {<br> String[] configLocations = { "<span style="color: #ff0000;">file:WebContent/WEB-INF/applicationContext.xml</span>"};<br> return configLocations;<br>}<br></span></p>
<p><span style="color: #ff0000;">AbstractXXXSpringContextTests</span>就会根据根据<span style="color: #ff0000;">getConfigLocations</span>方法返回的context xml位置的数组来加载<span style="color: #ff0000;">并且对加载的Context提供缓存</span>。 这是非常重要的,因为如果你在从事一个大项目时,启动时间可能成为一个问题--这不是Spring自身的开销,而是被Spring容器实例化的对象在实例 化自身时所需要的时间。例如,一个包括50-100个Hibernate映射文件的项目可能需要10-20秒的时间来加载上述的映射文件,如果在运行每个 测试fixture里的每个测试案例前都有这样的开销,将导致整个测试工作的延时,最终有可能(实际上很可能)降低效率。</p>
<p>在某种极偶然的情况下,某个测试可能“弄脏”了配置场所,并要求重新加载--例如改变一个bean的定义或者一个应用对象的状态--你可以调用 <code class="classname"><span style="color: #ff0000;">AbstractDependencyInjectionSpringContextTests</span></code> 上的 <code class="literal"><span style="color: #ff0000;">setDirty</span>()</code> 方法来重新加载配置并在执行下一个测试案例前重建application context</p>
<p></p>
<p>当类 <span style="color: #ff0000;">AbstractDependencyInjectionSpringContextTests</span><span style="color: #ff0000;">(及其子类)</span>装载你的Application Context时,你<span style="color: #0000ff;">可以通过Setter方法来注入</span>你想要的来自context的bean,而<span style="color: #0000ff;">不需要显式的调用applicationContext.getBean(XXX)</span>。因为AbstractDependencyInjectionSpringContextTests会从getConfigLocations()方法指定的配置文件中帮你自动注入</p>
<p>下面的例子就是通过setter方法来获得context里的ProductManager bean:</p>
<p>public class MyTest <span style="color: #ff0000;">extends AbstractDependencyInjectionSpringContextTests</span> {<br> ProductManager productManager;</p>
<p> public String[] <span style="color: #ff0000;">getConfigLocations</span>() {<br> String[] configLocations = { "file:WebContent/WEB-INF/applicationContext.xml" };<br> return configLocations;<br> }</p>
<p> public void testGetProduct() {<br> assertEquals("tomson",productManager.getProductByName("tomson").getName());<br> }<br></p>
<p><span style="color: #0000ff;"> //通过setter方法自动从context里注入productManager bean,而不用显示调用applicationContext</span><span style="color: #0000ff;">.getBean(XXX)</span><br> public void <span style="color: #ff0000;">setProductManager</span>(ProductManager productManager) {<br> this.productManager = productManager;<br> }<br>}</p>
<p>但是<span style="color: #ff0000;"><strong>如 果context里有多个bean都定义为一个类型(例如有多个bean都是ProductManager class类型的),那么对这些bean就无法通过setter方法来自动依赖注入(因为有多个bean同一个类型,不知要自动注入哪个)。在这种情况下 你需要显示的调用applicationContext.getBean(XXX)来注入</strong></span>。如:</p>
<p>public class MyTest extends AbstractDependencyInjectionSpringContextTests {<br> ProductManager productManager;</p>
<p> public String[] getConfigLocations() {<br> String[] configLocations = { "file:WebContent/WEB-INF/applicationContext.xml" };<br> return configLocations;<br> }</p>
<p>public void onSetUp() {<br><span style="color: #ff0000;"> productManager = (ProductManager) applicationContext.getBean("productManager");</span><br> }</p>
<p> public void testGetProduct() {<br> assertEquals("tomson",productManager.getProductByName("tomson").getName());<br> }<br><br>}</p>
<p>如果你的<span style="color: #ff0000;">TestCase不使用依赖注入,只要不定义任何setters方法即可</span>。<span style="color: #ff0000;">或者你可以继承 AbstractSpringContextTests</span> --这个 org.springframework.test 包中的根类,而不是继承<span style="color: #ff0000;">AbstractDependencyInjectionSpringContextTests(及其子类)</span>。这是<span style="color: #0000ff;">因为AbstractSpringContextTests 只包括用来加载Spring Context的便利方法但没有自动依赖注入的功能</span></p>

转载地址:http://kjaji.baihongyu.com/

你可能感兴趣的文章
23. Merge k Sorted Lists (Divide and conquer, Linked List) 以及java匿名内部类
查看>>
Tensorflow入门资料
查看>>
剑指_用两个栈实现队列
查看>>
剑指_顺时针打印矩阵
查看>>
剑指_栈的压入弹出序列
查看>>
剑指_复杂链表的复制
查看>>
服务器普通用户(非管理员账户)在自己目录下安装TensorFlow
查看>>
星环后台研发实习面经
查看>>
大数相乘不能用自带大数类型
查看>>
字节跳动后端开发一面
查看>>
CentOS Tensorflow 基础环境配置
查看>>
centOS7安装FTP
查看>>
FTP的命令
查看>>
CentOS操作系统下安装yum的方法
查看>>
ping 报name or service not known
查看>>
FTP 常见问题
查看>>
zookeeper单机集群安装
查看>>
do_generic_file_read()函数
查看>>
Python学习笔记之数据类型
查看>>
Python学习笔记之特点
查看>>