用笑话和酶模拟自定义 Hook 会导致 'xxx is not a function or its return value is not iterable' 错误
Mocking custom Hook with jest and enzyme results in 'xxx is not a function or its return value is not iterable' Error
我对笑话和酵素还很陌生。在我的项目中,我将使用基于 SPA React 的应用程序。包含数据的上下文提供程序,还有几个挂钩。我现在使用 Jest(使用 ts-jest 和 enzyme)
我的jest.config看起来像这样
module.exports = {
"roots": [
"<rootDir>/src"
],
"transform": {
"^.+\.tsx?$": "ts-jest"
},
"testRegex": "(/__tests__/.*|(\.|/)(test|spec))\.tsx?$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
],
"snapshotSerializers": ["enzyme-to-json/serializer"]
所以我的第一步是测试 UI 组件是否有效。
下一步是用模拟数据测试组件。但是我得到了底部描述的错误。
我有这样一个功能组件:
export default function CurrentWeather(props: ICurrentWeatherProps) {
const [data, Reload] = useCurrentWeather(props.locationID);
return (<div>......</div>)
}
你会注意到 useCurrentWeather
钩子,这里是它的代码:
import { useEffect, useState } from 'react';
import { useLocationState } from '../context/locationContext';
import { ILocationData } from './useLocations';
import _ from 'lodash';
...
export default function useCurrentWeater(locationId: number) {
const locationState = useLocationState();
const Reload = () => { GetData() }
const [Data, SetData] = useState<IWeatherDataInfo>({Id:0,ConditionIcon:'',Date:new Date(),MaxTemp:0, MinTemp:0});
async function GetData() { .... }
useEffect(Reload, [locationState.data, locationId]);
return [Data, Reload] as const;
}
现在我想嘲笑这些Hook。我尝试关注
import React from 'react';
import { configure, shallow, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import CurrentWeather from '../components/Weather/CurrentWeather';
import { IWeatherDataInfo } from '../Hooks/useWeaters';
configure({ adapter: new Adapter() });
const mockWeatherReload = jest.fn();
const mockdata: IWeatherDataInfo = { Date: new Date(), ConditionIcon: "", MinTemp: 0, MaxTemp: 10 };
jest.mock('../Hooks/useCurrentWeather', () => ({
useCurrentWeather: jest.fn(()=>{ [mockdata, mockWeatherReload]})
}));
describe("WeatherWidget", () => {
it("RenderOnlyAddButton", () => {
const container = shallow(<CurrentWeather locationID={1} hidden={false} />);
});
});
现在,当我执行这个测试时,我会得到这个错误结果:
src/tests/WeatherWidget.test.tsx
● WeatherWidget › RenderOnlyAddButton
TypeError: (0 , _useCurrentWeather.default) is not a function or its return value is not iterable
9 |
10 | export default function CurrentWeather(props: ICurrentWeatherProps) {
> 11 | const [data, Reload] = useCurrentWeather(props.locationID);
| ^
12 | return (
我做错了什么?有什么我想念的吗?
这样试试:(下面应该是你的功能组件的测试文件)
const mockUseCurrentWeather = jest.fn();
jest.mock("put here the absolute path", () => ({
__esModule: true,
useCurrentWeather: (...args: any) => mockUseCurrentWeather(...args),
}));
describe("WeatherWidget", () => {
beforeEach(() => {
mockUseCurrentWeather.mockClear();
mockUseCurrentWeather.mockReturnValue([undefined, undefined]);
});
it("RenderOnlyAddButton", () => {
mockUseCurrentWeather.mockClear();
mockUseCurrentWeather.mockReturnValue([undefined, undefined]);
const container = shallow(<CurrentWeather locationID={1} hidden={false} />);
});
});
我对笑话和酵素还很陌生。在我的项目中,我将使用基于 SPA React 的应用程序。包含数据的上下文提供程序,还有几个挂钩。我现在使用 Jest(使用 ts-jest 和 enzyme)
我的jest.config看起来像这样
module.exports = {
"roots": [
"<rootDir>/src"
],
"transform": {
"^.+\.tsx?$": "ts-jest"
},
"testRegex": "(/__tests__/.*|(\.|/)(test|spec))\.tsx?$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
],
"snapshotSerializers": ["enzyme-to-json/serializer"]
所以我的第一步是测试 UI 组件是否有效。 下一步是用模拟数据测试组件。但是我得到了底部描述的错误。
我有这样一个功能组件:
export default function CurrentWeather(props: ICurrentWeatherProps) {
const [data, Reload] = useCurrentWeather(props.locationID);
return (<div>......</div>)
}
你会注意到 useCurrentWeather
钩子,这里是它的代码:
import { useEffect, useState } from 'react';
import { useLocationState } from '../context/locationContext';
import { ILocationData } from './useLocations';
import _ from 'lodash';
...
export default function useCurrentWeater(locationId: number) {
const locationState = useLocationState();
const Reload = () => { GetData() }
const [Data, SetData] = useState<IWeatherDataInfo>({Id:0,ConditionIcon:'',Date:new Date(),MaxTemp:0, MinTemp:0});
async function GetData() { .... }
useEffect(Reload, [locationState.data, locationId]);
return [Data, Reload] as const;
}
现在我想嘲笑这些Hook。我尝试关注
import React from 'react';
import { configure, shallow, mount } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
import CurrentWeather from '../components/Weather/CurrentWeather';
import { IWeatherDataInfo } from '../Hooks/useWeaters';
configure({ adapter: new Adapter() });
const mockWeatherReload = jest.fn();
const mockdata: IWeatherDataInfo = { Date: new Date(), ConditionIcon: "", MinTemp: 0, MaxTemp: 10 };
jest.mock('../Hooks/useCurrentWeather', () => ({
useCurrentWeather: jest.fn(()=>{ [mockdata, mockWeatherReload]})
}));
describe("WeatherWidget", () => {
it("RenderOnlyAddButton", () => {
const container = shallow(<CurrentWeather locationID={1} hidden={false} />);
});
});
现在,当我执行这个测试时,我会得到这个错误结果:
src/tests/WeatherWidget.test.tsx
● WeatherWidget › RenderOnlyAddButton
TypeError: (0 , _useCurrentWeather.default) is not a function or its return value is not iterable
9 |
10 | export default function CurrentWeather(props: ICurrentWeatherProps) {
> 11 | const [data, Reload] = useCurrentWeather(props.locationID);
| ^
12 | return (
我做错了什么?有什么我想念的吗?
这样试试:(下面应该是你的功能组件的测试文件)
const mockUseCurrentWeather = jest.fn();
jest.mock("put here the absolute path", () => ({
__esModule: true,
useCurrentWeather: (...args: any) => mockUseCurrentWeather(...args),
}));
describe("WeatherWidget", () => {
beforeEach(() => {
mockUseCurrentWeather.mockClear();
mockUseCurrentWeather.mockReturnValue([undefined, undefined]);
});
it("RenderOnlyAddButton", () => {
mockUseCurrentWeather.mockClear();
mockUseCurrentWeather.mockReturnValue([undefined, undefined]);
const container = shallow(<CurrentWeather locationID={1} hidden={false} />);
});
});