最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to mock dispatch with jest.fn() - Stack Overflow

programmeradmin2浏览0评论

For example, I want to know what has been dispatched and the argument. The action creator is asynchronous, but I don't care about its implementation, I just want to know if the component dispatches the correct action creator with the correct argument. I've tried this approach:

store.dispatch = jest.fn()

But I can't get any useful information:

I've tried to solve the problem by this way:

expect(store.dispatch.mock.calls[0].toString()).toBe(requestArticles().toString())

But I don't know the argument and I'm sure, that there are a better way to do this. Also of note, I'm using react-testing-library, so I can't use wrapper.instance().props from Enzyme.

For example, I want to know what has been dispatched and the argument. The action creator is asynchronous, but I don't care about its implementation, I just want to know if the component dispatches the correct action creator with the correct argument. I've tried this approach:

store.dispatch = jest.fn()

But I can't get any useful information:

I've tried to solve the problem by this way:

expect(store.dispatch.mock.calls[0].toString()).toBe(requestArticles().toString())

But I don't know the argument and I'm sure, that there are a better way to do this. Also of note, I'm using react-testing-library, so I can't use wrapper.instance().props from Enzyme.

Share Improve this question asked Jun 16, 2020 at 11:52 Ричард ФейнманРичард Фейнман 4892 gold badges6 silver badges10 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 9

Here's an example that worked for me (2022):

(Navbar.test.js)

import store from "../../store/redux-store";
import { useDispatch, useSelector } from "react-redux";
import { Provider } from "react-redux";

import configureStore from "redux-mock-store";
import { render, screen, cleanup, waitFor } from "@testing-library/react";
import userEvent from "@testing-library/user-event";

import Navbar from "../navbar/Navbar";

describe("Navbar", () => {

  beforeEach(() => {
    // ! WE MAKE SURE THE MOCKS ARE CLEARED BEFORE EACH TEST CASE
    useSelectorMock.mockClear();
    useDispatchMock.mockClear();
  });

  afterAll(() => {
    cleanup();
  });

  // ! SETUP THE SPY ON USESELECTOR / USE DISPATCH
  // ! WE DO THIS TO BE ABLE TO CHECK IF THE DISPATCH MOCK GOT CALLED AND HOW MANY TIMES
  const reactRedux = { useDispatch, useSelector }
  const useDispatchMock = jest.spyOn(reactRedux, "useDispatch");
  const useSelectorMock = jest.spyOn(reactRedux, "useSelector");

[...]

  test("cliking the sign-out button should sign out user", async () => {
    const mockStore = configureStore();
    const initialState = {
      auth: {
        isAuthModalOpen: false,
        user: { id: 1, email: "[email protected]" },
        notification: null,
        isLoggedIn: true,
        token: "ABC123",
      },
    };
    let updatedStore = mockStore(initialState);

    const mockDispatch = jest.fn();
    useDispatchMock.mockReturnValue(mockDispatch);
    updatedStore.dispatch = mockDispatch;
    // ? HERE THE INITIAL CONTENT OF THE MOCK
    // console.log(updatedStore.dispatch.mock);


    render(<Provider store={updatedStore}><Navbar /></Provider>);
    const signOutBtn = screen.getByTestId("button-sign-out");
    expect(signOutBtn).toBeInTheDocument();

    expect(updatedStore.dispatch).not.toHaveBeenCalled();
    userEvent.click(signOutBtn);
    // ? HERE THE CONTENT OF THE MOCK CHANGED
    // console.log(updatedStore.dispatch.mock);

    expect(updatedStore.dispatch).toHaveBeenCalledTimes(1);
    expect(updatedStore.dispatch.mock.lastCall[0].type).toMatch("destroySession");
    screen.debug()

    console.log(updatedStore.getActions());
  });

Notice the difference in the way of importing "useDispatch" from react-redux. Also, notice the way "mockDispatch" is attached to "updatedStore.dispatch".

Those 2 changes made it work for me.

You can mock the action file and check if the action has been called.

e.g. Lets say foo.action.js is the file which has the action being dispatched.

in the start of your test file before importing the component, you can mock the file as:

const yourActionMock = jest.fn();
jest.mock('<Path to the action file>/foo.action.js', () => ({
  yourAction: yourActionMock
}));

now you can test the action called as: expect(yourActionMock).toHaveBeenCalledWith(<args>)

if you're using react-redux hooks you can do it like so:

import * as reactRedux from 'react-redux';

const mockDispatch = jest.fn();
const mockUseDispatch = jest.spyOn(reactRedux, 'useDispatch');

and then make assertions on mockDispatch as usual.

发布评论

评论列表(0)

  1. 暂无评论