公司在用Mockito进行单元测试,写单测的时候总会遇到一些小问题,顺手记录下来。
二、遇到问题记录 2.1 mock update 报错 2.1.1 问题现象当update使用如下写法时,mock会报错
被mock代码示例:
mock语句:
when(platformMallOrderServcie.update(any())).thenReturn(true);
报错:
2.1.2 问题原因ERROR com.longfor.gf.lw.ordercenter.business.OrderBusiness - callbackMerchant回调异常,原因:cannot find column’s cache for “com.longfor.gf.lw.ordercenter.entity.PlatformMallOrder”, so you cannot used “class com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper”!
com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: cannot find column’s cache for “com.longfor.gf.lw.ordercenter.entity.PlatformMallOrder”, so you cannot used “class com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper”!
根据测试,发现只有update时使用lambda进行set操作会有问题。推测是mock框架和mybatis-plus框架有冲突。
2.1.3 解决方案解决方法有两个,两种方案均可实现mock不报错。
第一种解决方案:修改update写法
不使用lambda即可。修改后代码如下:
第二种解决方案:修改mock方法
除非mock时发现代码有问题,一般情况下,不会因为mock修改代码,那么就要修改mock方法。报错中提示是目标类没有加载进mybatis-plus的缓存中,那么mock时手动将其加载进缓存即可。代码如下:
根据版本号选择 TableInfoHelper.initTableInfo(null, PlatformMallOrder.class); 或 TableInfoHelper.initTableInfo(new MapperBuilderAssistant(new MybatisConfiguration(), ""), RefundTradeProcessPool.class);
改后如下:
TableInfoHelper.initTableInfo(null, PlatformMallOrder.class); when(platformMallOrderServcie.update(any())).thenReturn(true);
注:如果有其他方案,欢迎大家补充。
2.2 mock mybatis-plus生成的service报错 2.2.1 问题现象以PlatformMallGoodsServiceImpl类为例。此类定义如下
public class PlatformMallGoodsServiceImpl extends ServiceImplimplements IPlatformMallGoodsService
所以应该mock对应的mapper方法
when(platformMallGoodsMapper.update(any(PlatformMallGoods.claaa),any(UpdateWrapper.class))).thenReturn(1);
代码中有如下写法,mock时会报空指针
this.update(goodsUpdateWrapper)2.2.2 查找问题点
通过debug可以找到对应的报错代码
发现是mapper没有注进去。
原因是使用的注解不同
// mock目标类的注解 @InjectMocks private PlatformMallGoodsServiceImpl platformMallGoodsService; // 其他被mock的类 @Mock private ISecondhandGoodsDetailService secondhandGoodsDetailService;
@InjectMocks标记的类会被实例化,@Mock标记的类会被注入到@InjectMocks标记的类中。
2.2.4 解决方案mock方法中手动注入mapper即可,代码写法如下
ReflectionTestUtils.setField({@InjectMocks标记的类}, "baseMapper", {@InjectMocks标记的类对应的mapper});
按照上述写法,此例中添加的mock代码如下
ReflectionTestUtils.setField(platformMallGoodsService, "baseMapper", platformMallGoodsMapper);2.3 mock List失败 2.3.1 问题现象
@Mock一个List变量不生效,代码如下
@Mock private ListmockStrategies;
在真正运行时会报NPE,因为strategies为null,报错代码如下
for (TimeFormatStrategy strategy : strategies)2.3.2 问题原因
具体原因没有找到,我观察到在单测方法中list会被mock出来,但走到真正的方法内list就变成null了,仿佛mock没有生效。
参见:如何mock一个List类型的属性
将@Mock换成@Spy注解,然后增加一个赋值逻辑即可
@Spy private ListmockStrategies = new ArrayList<>(); // 不用一定放到Before里,放在对应的Test方法中也可以,我是懒得一个一个放就这么写了 @Before public void init() { mockStrategies.add(mockDefaultTimeFormatStrategy); }



