首页 > 解决方案 > TypeError: undefined is not a function when unit-testing custom redux hook

问题描述

我有一个自定义钩子,它调用一个 saga 函数,该函数又调用一个 axios api,在测试这个函数时我得到

类型错误:未定义不是函数

我只想测试这个函数是否被调用。

postHook.test.tsx

import { renderHook } from "@testing-library/react-hooks";
import usePostsHook from "./postsHook";
import { initCommentUpdates, getPostsInit } from "../actions/postActions";
import { getPosts } from "../selectors/selectors";
import { useSelector, useDispatch } from "react-redux";

describe("usePostsHook hook", () => {
    const [posts] = renderHook(() => usePostsHook());
    expect(posts).toHaveBeenCalledWith(1);
});

postHooks.tsx

import React from "react";
import { useDispatch, useSelector } from "react-redux";
import { initCommentUpdates, getPostsInit } from "../actions/postActions";
import { getPosts } from "../selectors/selectors";
function usePostsHooks() {
    const dispatch = useDispatch();
    const posts = useSelector(getPosts());
    React.useEffect(() => {
        dispatch(getPostsInit());
        console.log("post hooks got called");
        dispatch(initCommentUpdates());
    }, []);
    return [posts];
}

export default usePostsHooks;

标签: reactjsredux

解决方案


posts不是你的钩子中的一个函数,而是从商店中选择的东西,我认为是你的 API 的返回。所以expect(posts).toHaveBeenCalledWith(1);很自然,因为它不是一个函数。

要测试您的调度是否发生,您需要模拟它。这是我在测试中使用的示例:

import * as ReactRedux from 'react-redux';

// this mock will be the dispatch function that redux returns on useDispatch()
const mockDispatch = jest.fn();

beforeAll(() => {
  // tells useDispatch to return the mocked dispatch
  ReactRedux.useDispatch = jest.fn().mockImplementation(() => mockDispatch);
  // tells useSelector to return an empty array
  ReactRedux.useSelector = jest.fn().mockImplementation(() => []);
});


beforeEach(() => {
  // clear the mocks to refresh their calls info
  ReactRedux.useDispatch.mockClear();
  mockDispatch.mockClear();
});

稍后,在您的测试中

expect(posts).toEqual([])
expect(mockDispatch).toHaveBeenCalledWith(getPostsInit())

这里的事情是你只是对你的钩子进行单元测试,即:它返回返回的内容useSelector,它触发一些调度,而不知道 or 的实际实际实现是useSelector什么useDispatch


推荐阅读