Android Studio单元测试Days.daysBetween随机执行失败如何解决?
单元测试偶现少1天问题根因与修复方案
问题根因
这个偶现失败是因为两次获取当前时间的时点刚好跨零点导致的:
- 测试代码构造
testDate时调用LocalDate(Date())获取了第一次当前日期 - 调用业务方法时,业务代码内部再次调用
LocalDate(Date())获取第二次当前日期
两次获取操作存在毫秒级的时间差,如果这个时间差刚好跨过自然日零点(比如第一次取时间是23:59:59.999,第二次已经是次日00:00:00.001),两次得到的当前日期就相差1天,最终计算出的剩余天数就会比预期少1,只有刚好跨零点的场景才会触发,所以表现为偶现失败。
修复方案
核心思路是避免业务代码内部隐式生成当前时间,将时间作为可传入的参数,保证测试时构造用例和计算差值用的是同一个时间基准。
业务代码修改
将当前时间作为参数抽离,保留原有对外调用的默认实现:
internal fun getRemainingDays(itemDate: Date?): Int? { // 正常业务调用时默认传当前时间 return getRemainingDays(itemDate, Date()) } // 包可见方法,供测试时传入固定时间 internal fun getRemainingDays(itemDate: Date?, now: Date): Int? { if (itemDate == null) return null return Days.daysBetween(LocalDate(now), LocalDate(itemDate)).days }
测试代码修改
测试时使用同一个时间基准构造测试数据和调用业务方法:
@Test fun getRemainingDays() { val fixedNow = Date() val testDate = LocalDate(fixedNow).plusDays(2).toDate() assertThat(viewModel.getRemainingDays(testDate, fixedNow), equalTo(2)) }
如果不想修改原有方法签名,也可以统一封装全局时间获取工具类,用Mock框架在测试时固定工具类返回的当前时间,同样可以解决偶现问题。
内容的提问来源于stack exchange,提问作者DoctorWho
相关产品推荐
相关产品推荐

