You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用useContext解构导致Jest单元测试失败

解决Jest单元测试中useContext导入函数导致的失败问题

问题现象

使用Jest进行单元测试时,通过useContext导入的loginUser函数导致测试失败,报错信息如下:

TypeError: Cannot destructure property 'loginUser' of '(0 , _react.useContext)(...)' as it is undefined.

测试代码

test('Login page renders with no errors', () => {
    render(<Router><Login/></Router>)
});

Jest配置

module.exports = {
    preset: "ts-jest/presets/js-with-ts",
    transform: {
        '^.+\\.(js|jsx|ts|tsx)$': '<rootDir>/node_modules/react-scripts/config/jest/babelTransform.js',
        '^.+\\.css$': '<rootDir>/node_modules/react-scripts/config/jest/cssTransform.js',
        '^(?!.*\\.(js|jsx|ts|tsx|css|json)$)': '<rootDir>/node_modules/react-scripts/config/jest/fileTransform.js',
        "^.+\\.(js|jsx)$": "<rootDir>/node_modules/babel-jest-amcharts",
        "\\.[jt]sx?$": "babel-jest",
        "^.+\\.css$": "jest-transform-css",
        "node_modules/variables/.+\\.(j|t)sx?$": "ts-jest",
    },
    transformIgnorePatterns: [
//      '[/\\\\]node_modules[/\\\\].+\\.(js|jsx|ts|tsx)$',
        '^.+\\.module\\.(css|sass|scss)$',
        "[/\\\\]node_modules[/\\\\](?!(@amcharts)\\/).+\\.(js|jsx|ts|tsx)$",
        "/node_modules/(?!react-file-drop)",
        "node_modules/(?!variables/.*)"
    ],
    moduleNameMapper: {
        '^react-native$': 'react-native-web',
        '^.+\\.module\\.(css|sass|scss)$': 'identity-obj-proxy',
        "\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/mocks/fileMock.js",
        "\\.(css|less)$": "<rootDir>/mocks/fileMock.js",
        "^.+\\.(css|less|scss)$": "babel-jest",
    },
    moduleDirectories: ["node_modules", "src"],
}

loginUser实现代码

const loginUser = async (tokens) => {
    let response = await axios.post('http://127.0.0.1:8000/api/token/',tokens)
    try {
        setAuthTokens(authTokens => ({
            ...response.data
        }))
        const decoded = jwt_decode(response.data.access)
        setUser(user => ({
            ...decoded
        }))            
        localStorage.setItem('authTokens',JSON.stringify(response.data))
        history.push('/')
    }
    catch(err) {
        alert(response.data.user);
    }
}

解决方案

核心原因

测试时Login组件依赖的Context没有被提供,useContext返回undefined,导致解构loginUser失败。

具体解决步骤

  1. 在测试中手动提供Context Provider
    假设你的Context是AuthContext,修改测试代码,模拟Context中的loginUser函数:
    import { render } from '@testing-library/react';
    import { AuthContext } from './path-to-your-auth-context';
    import { Router } from 'react-router-dom';
    import Login from './Login';
    
    test('Login page renders with no errors', () => {
        // 模拟loginUser函数
        const mockLoginUser = jest.fn();
    
        render(
            <AuthContext.Provider value={{ loginUser: mockLoginUser }}>
                <Router>
                    <Login />
                </Router>
            </AuthContext.Provider>
        );
    });
    
  2. 处理多Context依赖
    如果组件依赖多个Context,需要嵌套所有必要的Provider,确保每个Context都有模拟值。
  3. 验证配置合理性
    当前jest.config无直接影响Context解析的问题,可检查moduleDirectories是否包含Context所在目录,确保测试能正确导入Context文件。

额外优化建议

  • 将Context模拟封装成工具函数,减少重复代码;
  • 对loginUser中的异步操作和副作用做mock处理:
    • 用jest.mock('axios')模拟接口请求;
    • 用jest.spyOn(localStorage, 'setItem')监听localStorage操作;
    • 用MemoryRouter替代Router,更方便测试路由跳转逻辑。

内容的提问来源于stack exchange,提问作者Emm

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 21:06:18