【问题标题】:React Testing Error: Uncaught [TypeError: Cannot read property 'map' of undefined]React 测试错误:未捕获 [TypeError:无法读取未定义的属性“地图”]
【发布时间】:2021-09-07 11:25:31
【问题描述】:

所以我正在测试一个组件,该组件使用我制作的名为“useFetch”的自定义钩子。我尝试为组件模拟 useFetch,然后我的组件中的 .map 调用给了我错误:错误:未捕获 [TypeError:无法读取未定义的属性“地图”]

这是我第一次为我的项目编写测试,所以我确定我在这里做错了什么,不知道如何继续。有没有办法通过我的组件的初始渲染?

useFetch.js

import React, { useState, useEffect } from 'react';
import { useAuth } from '../context/AuthContext';
import firebase from '../firebase'

const useFetch = () => {
    const [timerData, setTimerData] = useState({
        error: null,
        loading: true,
        timerList: []
    });
    const { getUuid } = useAuth();

    useEffect(() => {
        const unsubscribe = firebase
            .firestore()
            .collection('users')
            .doc(getUuid())
            .collection('timers')
            .onSnapshot((snapshot) => {
                const newTimers = snapshot.docs.map((doc) => ({
                    ...doc.data(),
                    id: doc.id
                }))
                newTimers.sort(function (x, y) {
                    return x.timerHistory[0].timeStamp - y.timerHistory[0].timeStamp;
                })
                setTimerData({
                    error: null,
                    loading: false,
                    timerList: newTimers
                },
                    (error) => {
                        setTimerData({
                            error,
                            loading: false,
                            timerList: []
                        })
                    }
                )
            })
        return () => unsubscribe();
    }, [])
    return timerData;
}

export default useFetch;

我正在测试的组件:TimerList.js

import ToggleableTimerForm from "./ToggleableTimerForm";
import TimerController from "./TimerController";
import useFetch from "../../hooks/useFetch";

const TimerList = () => {
    const { error, loading, timerList } = useFetch();
    return (
                <div className="timerlist column">
                    <ul className="row timerGrid">
                        {timerList.map(timer => {
                            return (<TimerController timer={timer} key={timer.id} />)
                        })}
                        <ToggleableTimerForm />
                    </ul>
                </div>
    );
}

export default TimerList;

我的测试:TimerList.test.js

import React from "react";
import TimerList from "../TimerList";
import { render, fireEvent, screen, cleanup } from "@testing-library/react";
import "@testing-library/jest-dom/extend-expect";

jest.mock("../../../hooks/useFetch", () => ({
    __esModule: true,
    default: () => ({
        timerData: {
            error: null,
            loading: true,
            timerList: [{
                id: "fakeid",
                name: "timer1"
            }]
        }
    }),
}));

jest.mock('../../../firebase', () => ({
    firebase: {
        firestore: jest.fn(() => ({})),
    },
}));

describe('<TimerList />', () => {
    it('renders the initial <TimerList />', () => {
        const { queryByTestId } = render(
                <TimerList />
        );
    });
});

编辑:通过按照 tromgy 的建议更改我的模拟的形状来解决这个问题。

jest.mock("../../../hooks/useFetch", () => ({
    __esModule: true,
    default: () => ({
        error: "",
        loading: false,
        timerList: []
    }),
}));

【问题讨论】:

  • 你必须从jest.mock("../../../hooks/useFetch",中删除额外的..

标签: javascript reactjs firebase unit-testing jestjs


【解决方案1】:

我认为问题在于模拟函数返回的对象的形状与真正的 useFetch 的形状。

真正的函数返回:

{
  error: string, // that's an assumption
  loading: bool,
  timerList: Array
}

当模拟函数返回时:

{
  timerData: {
    error: string,
    loading: bool,
    timerList: Array
  }
}

【讨论】:

  • 哇,非常感谢!我改变了返回的形状,我的测试通过了。这让我头疼了好几个小时,再次感谢!
猜你喜欢
  • 2018-05-01
  • 2021-09-20
  • 1970-01-01
  • 2023-03-23
  • 2022-12-21
  • 2017-03-26
  • 2021-09-09
  • 2020-09-16
  • 2020-03-09
相关资源
最近更新 更多