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

RN+Redux+Jest异步函数测试报错:如何Mock导入的Store?

How to Mock Redux Store in Jest for React Native API Functions That Dispatch Actions

I see the issue here—you're directly importing your real Redux store into your API utility functions, which creates a hard dependency that breaks Jest tests (since the real store has middleware, sagas, and other setup that isn't optimized for testing). Let's fix this by mocking the store module entirely so your tests can run in isolation.

Step 1: Mock the Store Module in Your Test File

In your test file (e.g., api/__tests__/base.test.js), use Jest's jest.mock() to override the store import. We'll create a mock store with a spy on the dispatch method so we can verify it's called correctly when expected.

// api/__tests__/base.test.js
import { fetchAuthenticated, fetchAnonymous, APIError } from '../base';
import { getToken } from '../session';

// Mock the entire store module with a spy for dispatch
jest.mock('store', () => ({
  __esModule: true,
  default: {
    dispatch: jest.fn(),
  },
}));

// Mock getToken since fetchAuthenticated relies on it to check auth state
jest.mock('../session', () => ({
  getToken: jest.fn(),
}));

Step 2: Write Test Cases to Verify Behavior

Now you can write targeted tests to confirm that dispatch is called with the SESSION_LOGOUT action in the right scenarios, and that your functions return the correct error objects.

Test Case 1: fetchAuthenticated dispatches SESSION_LOGOUT when no token exists

describe('fetchAuthenticated', () => {
  it('dispatches SESSION_LOGOUT and returns a 401 error when token is missing', async () => {
    // Simulate unauthenticated user by making getToken return null
    getToken.mockResolvedValue(null);

    const result = await fetchAuthenticated('/test-path', {});

    // Verify dispatch was triggered with the correct action
    const mockStore = require('store').default;
    expect(mockStore.dispatch).toHaveBeenCalledWith({ type: 'SESSION_LOGOUT' });

    // Verify the returned error matches expectations
    expect(result.error).toBeInstanceOf(APIError);
    expect(result.error.status).toBe(401);
    expect(result.error.message).toBe('missing token');
  });
});

Test Case 2: fetchAnonymous dispatches SESSION_LOGOUT on 401/403 responses

For this test, you'll need to mock the global fetch function to return a 401 response:

describe('fetchAnonymous', () => {
  beforeEach(() => {
    // Reset the dispatch spy before each test to avoid cross-test contamination
    const mockStore = require('store').default;
    mockStore.dispatch.mockClear();
  });

  it('dispatches SESSION_LOGOUT when receiving a 401 response', async () => {
    // Mock fetch to return a 401 unauthorized response
    global.fetch = jest.fn().mockResolvedValue({
      status: 401,
      json: jest.fn().mockResolvedValue({ error: 'Unauthorized' }),
    });

    const result = await fetchAnonymous('/test-path', {});

    const mockStore = require('store').default;
    expect(mockStore.dispatch).toHaveBeenCalledWith({ type: 'SESSION_LOGOUT' });
    expect(result.error).toBeInstanceOf(APIError);
    expect(result.error.status).toBe(401);
  });
});

Why This Works

By mocking the store module, we replace the real Redux store with a minimal mock that only tracks calls to dispatch. This isolates your API functions from the rest of your app's Redux setup (like sagas or navigation middleware), so your tests don't have to handle those heavy dependencies.

We also mock getToken and fetch to control the inputs to your functions, letting you test specific scenarios (missing token, 401 response) without relying on a real backend or user auth state.

Bonus: Improve Long-Term Maintainability

If you find yourself mocking the store in many test files, you can create a reusable global mock in your Jest setup file (jest.setup.js):

// jest.setup.js
jest.mock('store', () => ({
  __esModule: true,
  default: {
    dispatch: jest.fn(),
  },
}));

Then add this setup file to your jest.config.js to apply the mock across all tests:

module.exports = {
  setupFilesAfterEnv: ['./jest.setup.js'],
  // other Jest config options...
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:24:10