单元测试相关:spring test、mockito、h2

单元测试相关:spring test、mockito、h2

背景

本文讨论单元测试,在单测中遇到的迷惑。单测中测一次就删除数据下次就没法再测怎么办,第三方的接口很不稳定我们要怎么测,整个业务规则这么多限制和要求怎么办? 你领导压缩工期没有足够单测的时间怎么办?

关于mockito和h2相关的,后续再发文,敬请不要期待,later is never~

啰嗦

先总结一波目前单测遇到的问题,比较杂,想到什么写什么,罗啰嗦

  • 无spring容器启动的单元测试,基本没什么用,因为现在的project都是用spring的,你不注入bean根本就没法测

  • 有spring容器启动的单测,我叫 spring test(你们是怎么称呼的?)

  • 国内程序员做单测,很少用断言,基本上都是运行单测并打印结果,肉眼观察结果对不对。这是个习惯问题

  • 国内领导很少给开发任务留单测的时间,有时候测试花的时间可能比开发还要多,但是很多领导没这样的意识,从而导致单测被草草执行,通常成为时间不足压缩的对象。所以追求覆盖率的单测常常流于形式或者应付(单测保证都难还要求覆盖率)。但是话说回来,写单测还是有好处的,静下心,静下心。。。

  • 单测,很多人都是测service层的接口,而不是从Controller层开始测,从而可能导致有些入参判断逻辑没测到(特别是在Controller写重逻辑的)

  • 单测,可以直接调用Controller方法进行测试,但是这种情况是接口的直接调用,所以对于@RequestParam 和 hibernate-validator(jsr303)这些校验,都测不到(因不触发检测),所以必须发起http请求测

  • 发起http请求测,可以用spring带的MockMvc,这种情况jsr303的参数校验是可以被激活的,会测得全一点

  • 对于一些接口,特别是第三方的接口,我们可以用mockito等框架进行mock测试。这类型的接口同样要么还在开发中未ready,要么是未部署或环境问题,或运行中响应慢等等因素可能会导致单测失败,推荐mock掉。

  • 单测后,数据有可能被改变,我们怎么样回滚? 有些测试是有前置条件的,比如查某个数据,查不到时时接口无法继续,那我们怎么测试? 大家共用单测的数据库,你的数据是可能被同事删掉的

    • 使用@Translational注解@Test方法,可以回滚数据,这样可以防止单测后数据改变

    • 可以在单测 “查询接口” 的时候,先插入数据,这样每次查询时都存在

    • 用内存数据库h2,我们换了思路,不操作实际的库,操作这个内存库

      但是前提是这个内存数据库有这些表结构和数据

      • h2提供了在单测前执行sql脚本初始化所需表和数据的功能,这样就有表和数据了。(整理建表语句、insert语句、解决sql写法的差异是个耗时工作

        TIP:
        h2可以设置MODE是MYSQL、PostgreSQL等,有点设置方言的意思,即把h2当成你想要的类型的数据库,这样特殊写法的sql才能执行成功(例如mysql里可以用on duplidate,但h2里会报错,指定MODE=MYSQL后可以解决)
        
        `spring.datasource.url=jdbc:h2:mem:test;MODE=MYSQL`
        
        但是这个MODE 不是指定了库的种类就完事,例如,即使MODE=PostgreSQL,执行本不该报错的`on conflict` 语句时还是报错。又如DDL建表,从Navicat导出来的,也不是不加修改就可执行成功,这也是麻烦点
        
      • 还有一个办法,是通过jpa hibernate的反向工程生成表结构,这样就不需要整理表结构(美好的愿望

        通过jpa hibernate,在数据库表POJO,写上一定的注解,开启hibernate的反向工程,似乎能够解决。
        
        本来项目是用Mybatis的,现在为了这个事情,需要添加jpa的注解
        
        表是生成了,但是数据似乎还是需要插入,怎么插入,可以用Mybatis或jpa的方式插入,其实也还是很麻烦
        

总结

对于单测,总结几点

  1. 不要搞什么h2,不实用。整理sql脚本生成表并插入数据,麻烦,而且后期还要维护表变更等。又不是直接Navicat导出表结构和数据的sql就能用,还得整理。

  2. 也不要搞什么jpa反向工程生成表,且不说这种情况能不能顺利生成表,初始化数据还是得老实写,方便些可能还不如sql脚本导入

  3. 直接就使用共同的库进行单测,这些情况这么解决

    1. 删除数据:加上@Translational,回滚。或者你要测试删除,则自己先新增,再删除

    2. 某个业务接口需要数据先存在,但是保证不了数据不被同事删除:自己在测试中先新增,再查询

    3. 依赖第三方接口:用mockito

    4. 其他的业务依赖:具体问题具体解决

      比如新增xxx,有业务要求xxx的name字段不能重复,我怎么保证单测时插入的数据不重复?
      可以使用用随机名字,要是随机都重复了,那就认命。(你也可以较真,去数据库先查一把所有name,然后锁住表,再插入不重复的name)
      
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值