繁体   English   中英

如何使用 jest.fn() 模拟调度

[英]How to mock dispatch with jest.fn()

例如,我想知道发送了什么以及参数。 动作创建者是异步的,但我不关心它的实现,我只想知道组件是否使用正确的参数调度了正确的动作创建者。 我试过这种方法:

store.dispatch = jest.fn()

但我无法获得任何有用的信息:

这是我可以从 store.dispatch.mock 得到的

我试图通过这种方式解决问题:

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

但我不知道这个论点,我敢肯定,有更好的方法来做到这一点。 另外值得注意的是,我使用的是 react-testing-library,所以我不能使用 Enzyme 的wrapper.instance().props

您可以模拟操作文件并检查该操作是否已被调用。

例如,可以说foo.action.js是具有正在调度的操作的文件。

在导入组件之前的测试文件的开头,您可以将文件模拟为:

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

现在您可以测试名为的操作: expect(yourActionMock).toHaveBeenCalledWith(<args>)

如果您使用的是 react-redux 挂钩,您可以这样做:

import * as reactRedux from 'react-redux';

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

然后像往常一样在mockDispatch上做出断言。

这是一个对我有用的例子(2022):

(导航栏.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: "test@test.com" },
        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());
  });

注意从 react-redux 导入“useDispatch”的方式的不同。 另外,请注意“mockDispatch”附加到“updatedStore.dispatch”的方式。

这两个变化使它对我有用。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM