Jasmine spy调用withArgs时无法正确匹配Date对象参数问题
Jasmine中withArgs匹配Date对象参数的解决方案
问题原因
Jasmine的withArgs()默认对非原始类型参数使用引用相等(===)做匹配,哪怕两个Date实例指向同一个时间点,只要不是同一个对象引用,就会判定为不匹配,这就是配置了mock规则仍然提示未找到对应调用的根本原因。
可行方案
方案1:自定义不对称匹配器(推荐,最贴合withArgs使用习惯)
Jasmine原生支持在withArgs中传入不对称匹配器,不需要修改原有mock的链式写法,只需要自定义一个日期值匹配器即可:
/** * 生成Date类型参数的匹配器,按时间戳比对日期值而非引用 * @param expectedDate 预期的日期对象 */ function sameDate(expectedDate: Date): jasmine.AsymmetricMatcher<Date> { return { asymmetricMatch(actual: unknown): boolean { return actual instanceof Date && actual.getTime() === expectedDate.getTime(); }, jasmineToString(): string { return `<date value equal to ${expectedDate.toISOString()}>`; } }; }
配置mock时直接用匹配器包裹预期日期即可,其余参数保持原有写法不变:
mockMyService = jasmine.createSpyObj<MyService>('mockMyService', ['getData']); // 替换原来直接传dateObj的写法 mockMyService.getData.withArgs(sameDate(dateObj1), /* 其余参数正常传入 */).and.returnValue(response1); mockMyService.getData.withArgs(sameDate(dateObj2), /* 其余参数正常传入 */).and.returnValue(response2);
这种方式的优势是可以和其他参数的默认匹配逻辑混用,每个参数的匹配规则独立,报错时Jasmine也会自动打印jasmineToString里定义的提示文本,排查问题很方便。如果项目里大量需要日期匹配,可以把这个工具函数抽到测试公共utils里复用。
方案2:使用callFake自定义返回逻辑
如果日期判断逻辑比较复杂,或者不想为每个日期单独写withArgs链,可以直接用callFake在回调里统一处理参数判断:
mockMyService.getData.and.callFake((dateParam: Date, /* 其余方法入参 */) => { const inputTimestamp = dateParam.getTime(); switch(inputTimestamp) { case dateObj1.getTime(): return response1; case dateObj2.getTime(): return response2; default: throw new Error(`未配置日期${dateParam.toISOString()}对应的mock响应,请检查测试用例逻辑`); } });
注意事项
- 比对Date值时优先用
getTime()获取时间戳做数值比对,比转ISO字符串效率更高,也不会受时区、字符串格式影响 - 不要依赖
describeWithDate解决Date匹配问题,它只能固定测试运行时的当前时间,无法解决不同Date实例的引用匹配问题 - 如果只需要校验参数是Date类型不需要校验具体值,直接用Jasmine内置的
jasmine.any(Date)即可,不需要自定义匹配器
内容的提问来源于stack exchange,提问作者Cean Manzano
相关产品推荐
相关产品推荐

