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

如何在Jest中Mock使用$自动订阅语法的Svelte Stores?

问题核心原因

你当前的Mock写法将store导出项包装为了返回store实例的函数,而Svelte的$自动订阅语法要求绑定的对象本身是持有subscribe方法的store实例。组件编译后会直接调用导入的user对象的subscribe方法获取值,但你Mock的user是一个Jest模拟函数,本身没有subscribe方法,必须调用后才会返回符合契约的store实例,因此会触发取值为undefined的报错。


解决方案

1. 基础静态Mock(无需在测试中修改store值)

直接导出符合store契约的实例即可,不要额外套函数,注意导出的变量名要和原store文件的导出名完全对应:

import { writable } from 'svelte/store';

jest.mock('../../stores/users', () => ({
  // 原store导出的变量名为user就写user,为currentUser就写currentUser
  user: writable({
    isAdmin: true
  })
}));

2. 动态修改store值(适配多测试用例不同状态)

如果需要在不同测试用例中切换store状态,可以提前定义Mock的store实例,在测试逻辑中直接调用set/update方法修改值:

import { writable } from 'svelte/store';

// 提前定义Mock的store实例,注意要写在jest.mock代码之前
const mockUserStore = writable({ isAdmin: false });

jest.mock('../../stores/users', () => ({
  user: mockUserStore
}));

test('普通用户不展示管理员标识', () => {
  mockUserStore.set({ isAdmin: false });
  // 渲染组件、执行断言逻辑
});

test('管理员展示管理员标识', () => {
  mockUserStore.set({ isAdmin: true });
  // 渲染组件、执行断言逻辑
});

注意:Jest执行时会将jest.mock代码提升到文件顶部执行,不要把Mock的store实例定义在jest.mock的回调函数内部,否则会出现变量引用错误。如果使用Svelte Testing Library,修改store值后建议使用waitFor或find*系列查询等待响应式更新完成后再执行断言。

3. 通用Mock工具函数

如果需要Mock多个store,可以封装通用的工具函数简化逻辑:

import { writable } from 'svelte/store';

function createMockStore(initialValue) {
  const { subscribe, set, update } = writable(initialValue);
  return {
    subscribe,
    set,
    update,
    // 可选:添加重置方法快速恢复初始状态
    reset: () => set(initialValue)
  };
}

// 使用示例
const mockUserStore = createMockStore({ isAdmin: false });
jest.mock('../../stores/users', () => ({
  user: mockUserStore
}));

额外排查项

如果按照上述方案修改后仍报错,可先检查jest.mock中填写的store文件路径,是否和组件内import的相对路径完全匹配,路径不一致会导致Mock不生效。

内容的提问来源于stack exchange,提问作者Ben Shurts

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 19:54:04