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

React Testing Library测试中onClick触发Context内dispatch函数报错的解决方案咨询

Fixing "TypeError: passwordModalDispatch is not a function" in Context Testing

The error you're hitting is super clear: your component expects to pull passwordModalDispatch and formDisplayDispatch from their respective Contexts, but your test only passes the state objects (passwordModalState and formDisplayState) in the Provider values. When the button clicks trigger those dispatch calls, the component can't find the functions—hence the TypeError.

Here's how to fix this, plus best practices for testing Context-dependent components:

Step 1: Mock the Dispatch Functions

Use Jest's jest.fn() to create mock dispatch functions. These will let the component call them without errors, and later you can assert that they were called with the exact arguments you expect.

Step 2: Update Your Test Context Values

Include the mock dispatch functions in the objects you pass to each Context Provider's value prop, matching the shape the component expects (since it uses object destructuring from useContext).

Revised Test Code

test('triggers correct dispatch actions when registration button is clicked', () => {
  // 1. Create mock dispatch functions
  const mockPasswordModalDispatch = jest.fn();
  const mockFormDisplayDispatch = jest.fn();

  // 2. Build complete Context values with both state AND dispatch
  const passwordModalContext = {
    passwordModalState: { isOpen: false },
    passwordModalDispatch: mockPasswordModalDispatch // Add this missing function
  };
  const formContext = {
    formDisplayState: { form: 'login' },
    formDisplayDispatch: mockFormDisplayDispatch // Add this missing function
  };

  const { container } = render(
    <FormDisplayContext.Provider value={formContext}>
      <PasswordModalContext.Provider value={passwordModalContext}>
        <HelpCards />
      </PasswordModalContext.Provider>
    </FormDisplayContext.Provider>
  );

  // 3. Trigger the button click
  const registerButton = screen.getByText(/register for online access/i);
  userEvent.click(registerButton);

  // 4. Assert the dispatch functions were called correctly
  expect(mockPasswordModalDispatch).toHaveBeenCalledWith({ type: 'CLOSE' });
  expect(mockFormDisplayDispatch).toHaveBeenCalledWith({ type: 'REGISTRATION' });
});

Bonus: Test the Login Button Flow

You can easily extend this to test the "Log in" card by adjusting the formDisplayState and updating your assertions:

test('triggers correct dispatch actions when login button is clicked', () => {
  const mockPasswordModalDispatch = jest.fn();
  const mockFormDisplayDispatch = jest.fn();

  const passwordModalContext = {
    passwordModalState: { isOpen: false },
    passwordModalDispatch: mockPasswordModalDispatch
  };
  // Set form to a non-login value so the "Already registered?" card renders
  const formContext = {
    formDisplayState: { form: 'registration' },
    formDisplayDispatch: mockFormDisplayDispatch
  };

  render(
    <FormDisplayContext.Provider value={formContext}>
      <PasswordModalContext.Provider value={passwordModalContext}>
        <HelpCards />
      </PasswordModalContext.Provider>
    </FormDisplayContext.Provider>
  );

  const loginButton = screen.getByTestId('loginBtn');
  userEvent.click(loginButton);

  expect(mockPasswordModalDispatch).toHaveBeenCalledWith({ type: 'CLOSE' });
  expect(mockFormDisplayDispatch).toHaveBeenCalledWith({ type: 'LOGIN' });
});

Key Takeaway

When testing components that consume Context, always make sure the Provider's value matches the exact shape the component expects. If your Context uses both state and dispatch (like most Redux-style Context setups), you need to include both in your test mocks. Using jest.fn() lets you verify that the component is dispatching the right actions, which is a critical part of testing stateful components.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 17:42:31