spring test独立ApplicationContext防止多个UT @Mockbean相互影响

15 篇文章 0 订阅

背景

之前出现过@MockBean的类在跑UT时报错,检查日志发现运行时没mock导致的报错,代码中明明是mock的,单独跑UT没问题,批量跑就出问题了,之前解决过相关问题记在代码注释中了,今天团队同学又出现了,记录下吧。
先看下面的两段代码

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = OpsApplication.class)
@WebAppConfiguration
public class RebuildInstanceSlaveControllerTest{
    @MockBean
    private DbinsBizInterface dbinsBizInterface;
    @Autowired
    private RebuildInstanceSlaveController rebuildInstanceSlaveController;
    @MockBean
    private DbfreeLockServiceService dbfreeLockServiceService;
    @MockBean
    private TaskActionBusiness taskActionBusiness;
    @MockBean
    private DbinsCellInterface dbinsCellInterface;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = OpsApplication.class)
@WebAppConfiguration
public class RestartInstanceControllerTest {

    @MockBean
    private DbinsBizInterface dbinsBizInterface;
    @Autowired
    private RestartInstanceController restartInstanceController;
    @MockBean
    private DbfreeLockServiceService dbfreeLockServiceService;
    @MockBean
    private TaskActionBusiness taskActionBusiness;
    @MockBean
    private DbinsCellInterface dbinsCellInterface;

从上面两段代码发现,@Mockbean的内容完全一致,只是各自@Autowired了相关bean,这两个UT类会共用一个spring ApplicationContext,检查共用不共用,只需在idea批量跑UT时看下就知道了,不共用的每个UT文件运行都会启动spring,如下图所示,没启动的就是共用了。
共用了的场景,RebuldInstanceSlaveControllerTest和RestartInstanceControllerTest共用了的场景:
在这里插入图片描述
没共用的场景如下图所示:
在这里插入图片描述

原理

spring test框架会缓存ApplicationContext,为了实现不相互影响,只有拥有一样的configuration的测试类才会缓存(在同一个springboot中执行)
当使用MockBean时会改变configuration,因为MockBean担心会与没Mock的地方相互影响
所以一个类的configuration=(@SpringBootTest(classes = OpsApplication.class)指定的class + MockBean 的bean)

按照上面逻辑第一段代码的configuration=(OpsApplication.class + DbinsBizInterface + DbfreeLockServiceService + TaskActionBusiness + DbinsCellInterface)

第二段代码的configureation=(OpsApplication.class + DbinsBizInterface + DbfreeLockServiceService + TaskActionBusiness + DbinsCellInterface)

可见这两个UT类的configureation相同,每次运行test都是顺序执行的,如果相邻两个test的configuration相同,则会在同一个context中执行两个test类,正好这两个又相邻,所以自然而然就在一个context中执行了

在同一个context中就会导致mock的地方可能会产生影响,批量执行时产生不可预期的报错。

解决

最好的解决办法就是不要在相同的context中执行,当然每个test类都独立context会让批量执行ut速度变慢
理解了上面的原理,只要configuration不同就好了,如何做到不同,最好的办法就是互斥,比如第一段代码里@Autowired
private RebuildInstanceSlaveController rebuildInstanceSlaveController;
如果此bean在第二段代码里不需要,那就直接mock了就好了
在第二段代码里添加如下就可以解决

@Mockbean
    private RebuildInstanceSlaveController rebuildInstanceSlaveController;

当时的注释
在这里插入图片描述

参考:https://github.com/spring-projects/spring-boot/issues/10015

  • 4
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值