前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring 测试:其实很简单

Spring 测试:其实很简单

作者头像
哲洛不闹
发布2018-09-14 15:03:19
1.1K0
发布2018-09-14 15:03:19
举报
文章被收录于专栏:java一日一条

在过去的职业生涯里,我经常发现有些人不写测试代码,而他们声称不写的理由是无法轻易地写出覆盖多个不同模块的测试用例。好吧,我相信他们中的大部分要么是缺乏一些比较易掌握的技术手段,要么就是没时间来把它搞清楚,毕竟工作中总会有进度之类的各种压力。因为不知道该如何测试,所以就经常忽略集成测试,由此带来的问题就是越来越糟糕的软件、越来越多的BUG和更加失望的客户。所以我想分享一些个人的经验,揭开集成测试神秘的面纱。

如何对基于Spring的工程更好地进行集成测试

使用工具: Spring, JUnit, Mockito

想象有这样一个Spring工程,它集成了一些外部服务,例如,一些银行的web服务。那么,为这个工程写测试用例以及在持续集成系统中完成这些测试时所遇到的问题基本都差不多:

  1. 每次测试都会有交易进行,每次交易都需要付出金钱成本,这些成本最终由客户承担;
  2. 测试时发出的过多的请求有可能被认为是恶意请求,可能造成在银行的账户被封,后果是测试失败;
  3. 当使用非生产环境进行测试时,测试结果并不十分可靠,同样,后果是测试失败。

通常情况下,你对单个类进行测试的时候,问题很容易解决,因为你可以虚拟一些外部服务来供调用。但是当对整个巨大的业务流程进行测试的时候,意味你需要对多个部件进行测试,这时,需要你将这些部件都纳入到Spring容器中进行管理。所幸,Spring包含了非常优秀的测试框架,允许你将来自生产环境配置文件中的bean注入到测试环境中,但是对那些被调用的外部服务,需要我们自己去写模拟实现。一般人第一反应可能是在测试的setUp阶段对由Spring注入的bean进行重新注入(修改),但是这种方法需要再仔细考虑一下。

警告:通过这种方式,你的测试代码打破了容器自身的行为,所以没法保证在真实的环境中也如你测试的结果一样。

事实上,我们无需先实现模拟类然后再把它重新注入到所需的bean中,我们可以让Spring帮助我们一开始就注入模拟类。让我们用代码演示一下。

示例工程包含一个名为BankService的类,代表调用的外部服务,一个名为UserBalanceService的类,它会调用BankService。UserBalanceService实现的非常简单,仅仅完成将余额从String向Double类型的转换。

BankService.java的源码:

BankServiceImpl.java的源码:

UserBalanceService.java的源码:

UserBalanceServiceImpl.java的源码:

然后是Spring的XML配置文件,添加所需要的bean声明。

applicationContext.xml的源代码:

下面是测试类UserBalanceServiceImplTest.java的源代码:

如我们预料的一样,测试方法报UnsupportedOperationException异常。我们现在的目的是把BankService换成我们的模拟实现。直接使用Mockito来生成factory bean的方法是没问题的,但是有更好的选择,使用Springockito框架。继续之前可以先大概了解一下。

剩下的问题就简单了:如何让Spring注入模拟的bean而不是真实的bean,在Spring 3.1版之前除了新建一个XML配置文件之外没有其他的方法。但是自从Spring引入了bean的profile定义之后,我们有了更加优雅的解决方式,虽然这种方式也需要一个额外的专门用作测试的XML配置文件。下面是这个用来测试的配置文件testApplicationContext.xml的代码:

做相应修改过之后的测试类UserBalanceServiceImplProfileTest.java的源代码:

你可能注意到了,在setUp方法里,我们定义了模拟的行为,并且在类上面加了@Profile的注解。这个注解激活了名为springTest的profile,因此使用Springockito模拟的bean就可以自动注入到任何它所需要的地方了。这个测试的运行结果会成功,因为Spring注入了Springockito 所模拟的版本,而不是applicationContext.xml里所声明的版本。

继续优化我们的测试

如果我们能将解决这个问题的方法更加推进一步的话,这篇文章看起来才没有缺憾。Springockito提供了另外一个名字叫作

Springockito Annotation的框架,它允许我们在测试类中使用注解来注入模拟类。继续看下去之前,您最好先去网站上大概瞧瞧。好了,下面是经过修改后的测试代码。

UserBalanceServiceImplAnnotationTest.java的源代码:

请注意,这里并没有新引入的XML配置文件,而是直接使用了正式环境的applicationContext.xml。我们使用@ReplaceWithMock这个注解标记了类型为BankService的bean,而后在setUp方法中对模拟类的行为进行了定义。

后记

Springockito-annotations项目有个巨大的优点,那就是,它使我们的测试代码建立在依赖覆盖的基础之上,通过这样,我们既不需要定义额外的XML配置文件,也不需要为了测试而去改动生产环境的配置文件。如果不使用Springockito-annotations的话,我们除了定义额外的XML配置文件别无他选了。因此,我强烈建议您在集成测试中使用Springockito-annotations,这样你可以最大限度减少测试用例对生产代码的影响,也能消除维护额外XML配置文件的负担。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2016-11-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java一日一条 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 如何对基于Spring的工程更好地进行集成测试
  • 继续优化我们的测试
  • 后记
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档