在Cypress测试中向全局window注入MobX对象后失去可观测性
问题原因
Cypress 的 cy.visit 回调 onLoad 运行在测试进程的上下文,而你的应用代码运行在浏览器页面的独立 JS 上下文,两者的 MobX 实例完全隔离:
onLoad里创建的EmployeeScheduleModel,是用测试上下文的 MobX 执行makeAutoObservable,对象的可观测元数据仅绑定到这个测试端的 MobX 实例。- 页面代码调用的
isObservable属于页面上下文的 MobX 实例,无法识别测试端 MobX 标记的对象,因此返回false。
解决方案
要让对象在页面上下文保持可观测性,必须让对象在页面上下文内被 MobX 处理,以下是两种可行方案:
方案1:传递配置而非实例,让页面自行创建可观测对象
- 测试端仅挂载创建实例所需的配置数据:
cy.visit("index.html", { onLoad(win) { win._EMP_SCHEDULE_CONFIG_ = { start: new Date(), end: new Date(), employee: new EmployeeModel(), shifts: ModelCollection.empty() }; }, });
- 应用端读取配置并创建实例(此时使用页面自身的 MobX):
// 应用启动逻辑 const config = window._EMP_SCHEDULE_CONFIG_; if (config) { const empSchedule = new EmployeeScheduleModel( config.start, config.end, config.employee, config.shifts ); console.log("Is observable: ", isObservable(empSchedule)); // 此时返回 true }
方案2:在页面上下文内直接创建可观测对象
通过 cy.window() 进入页面上下文执行创建逻辑,确保使用页面的 MobX:
cy.visit("index.html"); cy.window().then((win) => { // 此处代码运行在页面上下文,依赖页面环境的类和 MobX const empSchedule = new win.EmployeeScheduleModel( new win.Date(), new win.Date(), new win.EmployeeModel(), win.ModelCollection.empty() ); Object.defineProperty(win, "_EMP_SCHEDULE_", { value: empSchedule, writable: false, configurable: false, enumerable: true, }); console.log("Is observable: ", win.isObservable(empSchedule)); // 返回 true }); // 等待页面加载完成 cy.get(".sapFAvatar", { timeout: 500000 }); cy.get("#gifContainer", { timeout: 500000 }).should("not.exist");
注意:需确保 EmployeeScheduleModel、EmployeeModel 等类已通过全局变量或 UMD 打包暴露到页面的 window 对象上。
关键提示
- 禁止跨上下文传递 MobX 可观测对象,因为可观测元数据与当前环境的 MobX 实例强绑定。
- 测试向页面传递数据时,优先传递原始数据/配置,让页面自行创建可观测对象;或直接在页面上下文内执行实例化逻辑。
内容的提问来源于stack exchange,提问作者Joel
相关产品推荐
相关产品推荐

