单元测试中验证Mock返回数据的意义何在?
你这个疑惑太正常了!我刚用Mock框架写单元测试的时候也纳闷过——自己定义了Mock的返回值,再断言它不等于脱裤子放屁吗?但实际写多了就会发现,这类断言真的能帮你揪出不少问题,而且不全是因为改了Mock返回值才会失败。下面就说说几种常见的失败场景:
被测试代码传错了调用参数
比如你Mock的是emp.getName(1)返回Jim,但被测试的方法里,实际调用的时候不小心传成了emp.getName(0)或者emp.getName(1L)(注意参数类型不匹配)。这时候Mock的规则没被命中,框架会返回默认值(比如null、空字符串或者0),你的assertEquals("Jim", result)自然就失败了。这本质上是在验证:被测试代码有没有正确调用依赖方法,传对了参数。Mock的匹配规则写错了
有时候你以为自己写对了Mock规则,其实悄悄踩了坑。比如想用精确匹配eq(1),结果写成了anyInt();或者用复杂匹配器的时候逻辑写错了——比如本来想匹配大于5的id,写成了argThat(x -> x < 5)。这时候如果被测试代码传的是6,Mock就不会返回你预期的Jim,断言自然失败。这种情况是在帮你发现测试代码里的Mock配置错误。被测试代码对Mock返回值做了额外处理
假设你Mockemp.getName(1)返回Jim,但被测试方法里把返回值做了大写处理:return emp.getName(id).toUpperCase();。这时候你如果断言结果是Jim,就会失败(实际返回JIM)。这就帮你发现了被测试代码的逻辑不符合预期——你本来以为它会直接返回原始值,结果它偷偷做了转换。Mock规则被意外覆盖
有时候在测试方法里,你先配置了when(emp.getName(1)).thenReturn("Jim"),但后面又不小心加了一句when(emp.getName(1)).thenReturn("Mark")。这时候Mock的最终返回值是Mark,你断言Jim就会失败。这能提醒你测试代码里的Mock配置有冲突,避免后续测试出现奇怪的问题。调用了错误的重载方法
如果你的依赖服务有重载方法——比如emp有getName(int id)和getName(String id)两个方法,你Mock的是int参数的版本,但被测试代码里调用的是String参数的getName("1")。这时候Mock规则没命中,返回默认值,断言失败。这能帮你发现被测试代码调用了错误的方法重载。Mock框架版本变更导致行为变化
比如你升级了Mockito版本,某些匹配器的逻辑变了——比如旧版本里any()会匹配null,新版本里不会。这时候原来的Mock规则可能不再命中,返回默认值,断言失败。这其实是在提醒你:测试代码需要适配新的框架版本,避免因为框架升级导致测试失效。
总结一下:这类断言不是在测试Mock本身,而是通过Mock隔离依赖后,验证被测试代码是否正确地与依赖交互,以及是否正确处理了交互结果。它相当于在说:“我预期被测试代码会调用这个依赖方法并拿到这个值,然后返回给我——如果不是这样,说明代码逻辑有问题。”
内容的提问来源于stack exchange,提问作者user4235401

