React Context API 的 Jest & Enzyme 测试错误

IT技术 reactjs jestjs enzyme
2021-05-06 13:21:09

我正在使用 Jest 和 Enzyme 测试 React 应用程序。当我运行时,npm run test我收到了UserContext.jsx导入到MainPage.jsx. 我该如何解决?

错误信息

不变违规:无效的钩子调用。钩子只能在函数组件的主体内部调用。这可能是由于以下原因之一而发生的: 1. 你的 React 和渲染器的版本可能不匹配(例如 React DOM) 2. 你可能违反了 Hooks 规则 3. 你可能有多个 React 副本同一个应用

      11 | };
      12 | 
    > 13 | export const useUserValue = () => useContext(UserContext);
         |                                   ^

用户上下文.jsx

import React, {createContext, useContext, useReducer} from "react";

export const UserContext = createContext();

export const UserProvider = ({reducer, initialState, children}) => {
    return(
        <UserContext.Provider value={useReducer(reducer, initialState)}>
            {children}
        </UserContext.Provider>
    )
};

export const useUserValue = () => useContext(UserContext);

主页.test.js

import React from 'react';
import 'jest-styled-components';

import { configure, shallow, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import MainPage from "./MainPage";
import {useUserValue} from "../Context/UserContext";

configure({adapter: new Adapter()});

describe('Main Page Component', () => {

    it('exists', () => {
        const wrapper = shallow(<MainPage />, {context: useUserValue()});
        expect(wrapper).toMatchSnapshot();
    });
});

主页.jsx

import React, {useEffect, useState} from 'react';
import {useUserValue} from "../Context/UserContext";

export default function MainPage(props) {
    const [{ user }, dispatch] = useUserValue();

    return (
        <React.Fragment>
           {user.name}
        </React.Fragment>
    );
}
1个回答

错误说明是什么问题:

Hooks 只能在函数组件内部调用

这里钩子在组件外被错误地使用:

const wrapper = shallow(<MainPage />, {context: useUserValue()});

应该是{context: someContext },但问题是 Enzyme 渲染器接受旧版 React 上下文的上下文,该上下文不能特别影响上下文使用者和功能组件。

目前shallow不支持上下文提供者,需要使用mount

const wrapper = mount(
 <UserContext.Provider value={...}>
   <MainPage />
 </UserContext.Provider>
);

由于useUserValue位于它自己的module中,它可以单独测试并在使用它的组件中模拟,这样它就可以与shallow.

如果 React 和 ReactDOM 存在多个副本或版本不匹配,也会出现此错误,但事实并非如此。