Node+Prisma+Jest环境下date instanceof Date返回false的原因排查
问题:Prisma返回的Date对象无法通过
instanceof Date及Jest expect.any(Date)校验 使用环境
Node、Prisma 和 Jest
核心问题
从Prisma查询返回的deleted_at字段,除instanceof Date校验返回false外,其他所有日期校验逻辑均返回true;同时Jest测试中使用expect.any(Date)校验该字段会失败,但手动将其赋值为new Date后校验即可通过。
检测代码
const deletedUser = await app.prisma.user.findUnique({ where: { id: 1 }, }); console.log(deletedUser); console.log(typeof deletedUser.deleted_at); // object console.log(deletedUser.deleted_at.constructor); // [Function: Date] console.log(deletedUser.deleted_at.constructor.name); // Date console.log(deletedUser.deleted_at instanceof Date); // false console.log(deletedUser.deleted_at); // 2022-08-15T21:50:34.344Z console.log(Object.prototype.toString.call(deletedUser.deleted_at) === '[object Date]'); // true console.log(Object.prototype.toString.call(deletedUser.deleted_at)); // [object Date] console.log(new Date(deletedUser.deleted_at)); // 2022-08-15T21:50:34.344Z console.log(deletedUser.deleted_at.prototype); // undefined Object.keys(deletedUser.deleted_at).forEach(prop => console.log(prop)) console.log(Object.keys(deletedUser.deleted_at)); // [] console.log(deletedUser.deleted_at.__proto__); // {} console.log(isNaN(deletedUser.deleted_at)); // false console.log(deletedUser.deleted_at.valueOf()); // Mon Aug 15 2022 21:56:54 GMT+0000 (Coordinated Universal Time) console.log(Date(deletedUser.deleted_at.constructor.prototype));
分析过程
查阅相关资料后发现:
- 常规资料指出
instanceof Date会因对象跨上下文(如浏览器iframe)传递失效,且这种场景下Object.prototype.toString.call(date) === '[object Date]'也会返回false,但本次情况中该校验返回true,与常规跨上下文表现不符。 - Jest的
expect.any(Date)推测底层依赖instanceof逻辑,因此校验失败;仅当手动赋值new Date时,校验才能通过。 - Jest测试失败时,打印的
deleted_at显示为"deleted_at": Date {},但直接用console.log输出该值时,显示正常的日期字符串;手动赋值后测试输出正常的日期格式。
相关配置修改
为了复用应用实例缩短测试时间,在jest.config.js中配置全局app并挂载Prisma客户端:
const app = require('./tests/app'); const prisma = require('./prisma/client'); const request = require('supertest'); app.prisma = prisma; app.testRequest = request(app); module.exports = { testEnvironment: 'node', globals: { app, }, };
修改后测试时间从约130秒缩短至40秒,但怀疑该配置导致了上下文隔离,使得Date构造函数在不同上下文间不统一。
更新发现
附加到Array.prototype上的自定义函数在测试中也无法访问,进一步推测Jest会在每个测试前创建新的执行上下文,jest.config.js中添加的全局内容无法在测试期间稳定存在。根据Jest文档,globals中的数据不会在测试间持久化,具体保留内容不明确,无法依赖。
内容的提问来源于stack exchange,提问作者shmuels
相关产品推荐
相关产品推荐

