使用React Context API进行Jest&Enzyme测试错误

时间:2020-09-05 20:22:23

标签: reactjs jestjs enzyme

我正在用Jest&Enzyme测试React应用。运行npm run test时,我在UserContext.jsx中导入的MainPage.jsx中收到错误。我该如何解决?

错误消息

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

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

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);

MainPage.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();
    });
});

MainPage.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 个答案:

答案 0 :(得分:1)

该错误说明出了什么问题:

只能在函数组件的主体内部调用钩子

此处在组件外部未正确使用挂钩:

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

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

当前shallow doesn't support context providers,需要使用mount

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

由于useUserValue位于其自己的模块中,因此可以对其进行单独测试,并可以在使用它的组件中对其进行模拟,因此可以与shallow一起使用。

如果有多个副本或React和ReactDOM的版本不匹配,也会发生此错误,但这不是事实。

相关问题