You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 18:48:24