EmberJS中使用Sinon单元测试URL参数写入sessionStorage的问题
问题根因与修正方案
你的测试误判、逻辑不生效是几个叠加问题导致的:
- 自定义的
mockLocalStorage没有替换全局sessionStorage,路由执行时根本不会操作这个自定义对象,最后你手动调用mockLocalStorage.setItem塞值再断言,等于自行构造符合预期的结果,完全跳过了业务逻辑校验 - Sinon API 用法错误:
spy.calledWith()是执行完业务逻辑后的断言方法,不是用来配置spy规则的,写在visit()之前没有任何校验效果 - 路由代码本身存在API使用错误:Ember的transition对象中查询参数挂载在
to.queryParams下,不是你写的queryparam;且直接把整个参数对象存入sessionStorage时,会被转成"[object Object]"字符串,拿不到实际的userid值 - 多余stub了
sessionStorage.getItem,这段beforeModel逻辑根本没有读取storage的操作,多余的拦截反而可能干扰正常逻辑
修正后的代码
路由逻辑修正
beforeModel(transition) { // 从transition中正确取出查询参数 const queryParams = transition.to.queryParams; if (Object.prototype.hasOwnProperty.call(queryParams, 'userid')) { // 存入具体的userid值,不是整个参数对象 sessionStorage.setItem('user:id', queryParams.userid); } }
单元测试修正
测试时直接对原生sessionStorage的方法打spy,测试前后做好环境清理避免用例间污染,不要构造和业务逻辑完全隔离的mock对象:
import { module, test } from 'qunit'; import { visit } from '@ember/test-helpers'; import { setupApplicationTest } from 'ember-qunit'; import sinon from 'sinon'; module('Acceptance | page session storage logic', function(hooks) { setupApplicationTest(hooks); hooks.beforeEach(function() { // 测试前清空storage,缓存原生方法用于后续还原 sessionStorage.clear(); this.originalSetItem = sessionStorage.setItem; }); hooks.afterEach(function() { // 还原原生方法,清空storage,避免污染其他测试用例 sessionStorage.setItem = this.originalSetItem; sessionStorage.clear(); }); test('URL带userid参数访问页面时,会将参数值写入sessionStorage', async function(assert) { const setItemSpy = sinon.spy(sessionStorage, 'setItem'); const testUserId = '1234'; await visit(`/page?userid=${testUserId}`); // 校验spy捕获到了正确的setItem调用 assert.ok( setItemSpy.calledOnceWith('user:id', testUserId), 'setItem方法被以正确的key和value调用' ); // 直接读取真实storage做双重校验 assert.equal( sessionStorage.getItem('user:id'), testUserId, 'sessionStorage中实际存储的userid符合预期' ); }); test('URL不带userid参数访问页面时,不会修改sessionStorage对应值', async function(assert) { const setItemSpy = sinon.spy(sessionStorage, 'setItem'); // 预先写入一个测试值 const originalValue = 'existing-id'; sessionStorage.setItem('user:id', originalValue); await visit('/page'); // 校验没有触发对应key的写入操作 assert.notOk( setItemSpy.calledWith('user:id'), '无userid参数时不会写入storage' ); // 校验原有值未被篡改 assert.equal( sessionStorage.getItem('user:id'), originalValue, 'storage中原有值保持不变' ); }); });
内容的提问来源于stack exchange,提问作者dar
相关产品推荐
相关产品推荐

