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

如何使用Zustand和Jest测试异步状态更新?

Zustand Store异步方法测试问题解决

问题场景

我有如下listStore.js文件:

import { create } from 'zustand'
import queryList from '@/service'

const useListStore = () => create((get, set) => ({
   list: [],
   getList: async () => {
      const list = await queryList()
      const { updateList } = get()
      updateList(list)
   },
   updateList: list => {
      set({ 
       list: list.map(i => i + 1)
      })
   }
}))

为测试该Store Hook,编写了listStore.test.js测试文件:

import useListStore from './useListStore'
import { renderHook, act } from '@testing-library/react'

jest.mock('@/service', () => ({
  queryList: jest.fn().mockResolvedValue([1,2,3])
}))
describe('test listStore', () => {
   test('test updateList function', () => {
      // some codes
   })
   test('test getList function', () => {
      const { result } = renderHook(() => useListStore())
      act(() => result.current.getList())
      expect(queryList).toHaveBeenCalled()
      expect(result.current.list).toEqual([2,3,4])
   })
})

测试getList函数时,无法确保状态更新完成,即便用waitFor或await,拿到的list仍为旧值[],而非期望的[2,3,4]。

问题根源与解决步骤

1. 修复Store定义错误

你的useListStore写法有误:当前是每次调用useListStore()都会创建一个全新的Store实例,这不符合Zustand的使用规范,会导致状态无法在组件或测试中共享更新。

正确的Store定义:

import { create } from 'zustand'
import queryList from '@/service'

// 直接将create的返回值赋值给useListStore,无需包裹成函数
const useListStore = create((get, set) => ({
   list: [],
   getList: async () => {
      const list = await queryList()
      const { updateList } = get()
      updateList(list)
   },
   updateList: list => {
      set({ 
       list: list.map(i => i + 1)
      })
   }
}))

export default useListStore

2. 修正测试代码的异步处理

getList是异步函数,测试时必须等待其执行完成,同时Zustand的状态更新是异步的,需要用waitFor确保状态同步到Hook返回值后再断言。

修改后的测试代码:

import useListStore from './useListStore'
import { renderHook, act, waitFor } from '@testing-library/react'
import queryList from '@/service'

jest.mock('@/service', () => ({
  queryList: jest.fn().mockResolvedValue([1,2,3])
}))
describe('test listStore', () => {
   test('test updateList function', () => {
      // 你的测试代码
   })
   test('test getList function', async () => {
      const { result } = renderHook(() => useListStore())
      
      // 用async/await等待异步的getList执行完成
      await act(async () => {
        await result.current.getList()
      })
      
      // 验证queryList被调用
      expect(queryList).toHaveBeenCalled()
      
      // 用waitFor等待状态更新完成,再断言list的值
      await waitFor(() => {
        expect(result.current.list).toEqual([2,3,4])
      })
   })
})

关键说明

  • act包裹异步操作时必须使用async/await,确保异步函数执行完毕后再进行后续断言。
  • waitFor会持续检查断言条件,直到状态更新完成(默认超时时间1000ms),能有效解决Zustand状态更新与测试断言不同步的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 13:53:16