基本笑话测试收到“globalObj.setTimeout is not a function”错误
Receiving a `globalObj.setTimeout is not a function` error for basic jest test
我正在尝试测试基本的 Axios 挂钩并收到:
TypeError: globalObj.setTimeout is not a function
at setImmediatePolyfill (node_modules/@testing-library/react-native/build/helpers/timers.js:59:20)
at Object.then (node_modules/@testing-library/react-native/build/flushMicroTasks.js:26:32)
据我所知,预期的结果已经通过,但由于某种原因我仍然收到此错误,导致测试失败。这是对以下 package.json 的本机反应。该挂钩适用于我的应用程序,我假设它与测试库有关,但我不确定是什么。
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject",
"test": "jest"
},
"dependencies": {
"@react-navigation/native": "^6.0.6",
"@react-navigation/native-stack": "^6.2.5",
"@testing-library/jest-native": "^4.0.4",
"@testing-library/react-native": "^8.0.0",
"axios": "^0.24.0",
"eslint": "^8.2.0",
"expo": "^43.0.2",
"expo-status-bar": "^1.1.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-native": "^0.64.2",
"react-native-collapsible": "^1.6.0",
"react-native-safe-area-context": "^3.3.2",
"react-native-screens": "^3.9.0",
"react-native-web": "^0.17.5"
},
"devDependencies": {
"@babel/core": "^7.16.0",
"jest-expo": "^43.0.1",
"miragejs": "^0.1.42",
"react-hooks-testing-library": "^0.6.0",
"react-test-renderer": "^17.0.2",
"react-timer-mixin": "^0.13.4",
"xmlhttprequest": "^1.8.0",
"yarn-upgrade-all": "^0.5.4"
},
"private": true,
"jest": {
"preset": "react-native"
}
}
我的 Axios 挂钩:
// ./src/hooks.js
import { useState, useEffect } from "react";
export const useAPI = (apiFunction, params) => {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
apiFunction(params)
.then(({data}) => {
setData(data);
setIsLoading(false);
})
.catch((err) => {
setError("Something went wrong!");
setIsLoading(false);
});
}, [apiFunction, params]);
return [isLoading, data, error];
};
我的测试:
import { renderHook } from "@testing-library/react-hooks";
import { act } from "@testing-library/react-native";
import axios from "axios";
import { useAPI } from "../../Hooks/useAPI";
jest.mock("axios");
const mockData = {data: [{"test":"test"}]};
const getTestData = () => axios.get("/testEndpoint");
describe("fetch api data", () => {
describe("on success", () => {
it("should set data to test data and set isLoading false", async () => {
axios.get.mockResolvedValueOnce(mockData);
const {result, waitForNextUpdate } = renderHook(() => useAPI(getTestData));
await act( async () => {
await waitForNextUpdate();
})
const {data: expectedData} = mockData;
expect(result.current[0]).toEqual(false);
expect(result.current[1]).toEqual(expectedData);
expect(result.current[2]).toEqual(null);
})
})
})
解决了我自己的问题。我之前在 jest.setup.js 文件中设置了 global.window = {}
。 @testing-library/react-native 使用 timers.js 文件,他们在其中引用 globalObj
,他们从以下位置获得:const globalObj = typeof window === 'undefined' ? global : window;
。由于 window 在技术上并非未定义,globalObj 被设置为 {}
并且无法访问全局功能。
我正在尝试测试基本的 Axios 挂钩并收到:
TypeError: globalObj.setTimeout is not a function
at setImmediatePolyfill (node_modules/@testing-library/react-native/build/helpers/timers.js:59:20)
at Object.then (node_modules/@testing-library/react-native/build/flushMicroTasks.js:26:32)
据我所知,预期的结果已经通过,但由于某种原因我仍然收到此错误,导致测试失败。这是对以下 package.json 的本机反应。该挂钩适用于我的应用程序,我假设它与测试库有关,但我不确定是什么。
{
"main": "node_modules/expo/AppEntry.js",
"scripts": {
"start": "expo start",
"android": "expo start --android",
"ios": "expo start --ios",
"web": "expo start --web",
"eject": "expo eject",
"test": "jest"
},
"dependencies": {
"@react-navigation/native": "^6.0.6",
"@react-navigation/native-stack": "^6.2.5",
"@testing-library/jest-native": "^4.0.4",
"@testing-library/react-native": "^8.0.0",
"axios": "^0.24.0",
"eslint": "^8.2.0",
"expo": "^43.0.2",
"expo-status-bar": "^1.1.0",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-native": "^0.64.2",
"react-native-collapsible": "^1.6.0",
"react-native-safe-area-context": "^3.3.2",
"react-native-screens": "^3.9.0",
"react-native-web": "^0.17.5"
},
"devDependencies": {
"@babel/core": "^7.16.0",
"jest-expo": "^43.0.1",
"miragejs": "^0.1.42",
"react-hooks-testing-library": "^0.6.0",
"react-test-renderer": "^17.0.2",
"react-timer-mixin": "^0.13.4",
"xmlhttprequest": "^1.8.0",
"yarn-upgrade-all": "^0.5.4"
},
"private": true,
"jest": {
"preset": "react-native"
}
}
我的 Axios 挂钩:
// ./src/hooks.js
import { useState, useEffect } from "react";
export const useAPI = (apiFunction, params) => {
const [data, setData] = useState(null);
const [isLoading, setIsLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
apiFunction(params)
.then(({data}) => {
setData(data);
setIsLoading(false);
})
.catch((err) => {
setError("Something went wrong!");
setIsLoading(false);
});
}, [apiFunction, params]);
return [isLoading, data, error];
};
我的测试:
import { renderHook } from "@testing-library/react-hooks";
import { act } from "@testing-library/react-native";
import axios from "axios";
import { useAPI } from "../../Hooks/useAPI";
jest.mock("axios");
const mockData = {data: [{"test":"test"}]};
const getTestData = () => axios.get("/testEndpoint");
describe("fetch api data", () => {
describe("on success", () => {
it("should set data to test data and set isLoading false", async () => {
axios.get.mockResolvedValueOnce(mockData);
const {result, waitForNextUpdate } = renderHook(() => useAPI(getTestData));
await act( async () => {
await waitForNextUpdate();
})
const {data: expectedData} = mockData;
expect(result.current[0]).toEqual(false);
expect(result.current[1]).toEqual(expectedData);
expect(result.current[2]).toEqual(null);
})
})
})
解决了我自己的问题。我之前在 jest.setup.js 文件中设置了 global.window = {}
。 @testing-library/react-native 使用 timers.js 文件,他们在其中引用 globalObj
,他们从以下位置获得:const globalObj = typeof window === 'undefined' ? global : window;
。由于 window 在技术上并非未定义,globalObj 被设置为 {}
并且无法访问全局功能。