如何使用 Mock Service Worker 在自定义钩子中模拟获取?
Posted
技术标签:
【中文标题】如何使用 Mock Service Worker 在自定义钩子中模拟获取?【英文标题】:How to mock fetch in custom hook with Mock Service Worker? 【发布时间】:2021-09-19 12:06:51 【问题描述】:我想测试我的应用程序,该应用程序让用户输入一个向 Google Books API 发送请求的查询,然后显示响应。
我已将数据获取逻辑分离到其自己的自定义挂钩中。我想用 Mock Service Worker 来模拟 fetch。我在运行测试时收到了无效的钩子调用。
Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
3 |
4 | export const useBooksFetch = (initialUrl, initialData) =>
> 5 | const [url, setUrl] = useState(initialUrl);
| ^
6 | const [data, setData] = useState(initialData);
7 | const [isLoading, setIsLoading] = useState(false);
8 | const [isError, setIsError] = useState(false);
at resolveDispatcher (node_modules/react/cjs/react.development.js:1476:13)
at useState (node_modules/react/cjs/react.development.js:1507:20)
at useBooksFetch (src/hooks/useBooksFetch/useBooksFetch.js:5:25)
at Object.<anonymous> (src/hooks/useBooksFetch/useBooksFetch.test.js:78:24)
console.warn
[MSW] Found a redundant usage of query parameters in the request handler URL for "GET https://www.googleapis.com/books/v1/volumes?q=travel". Please match against a path instead, and access query parameters in the response resolver function:
rest.get("/books/v1/volumes", (req, res, ctx) =>
const query = req.url.searchParams
const q = query.get("q")
)
4 |
5 | const server = setupServer(
> 6 | rest.get(
| ^
7 | "https://www.googleapis.com/books/v1/volumes?q=travel",
8 | (req, res, ctx) =>
9 | return res(
确认
在运行npm ls react-dom
和 npm ls react
时确认匹配的 React 版本,并返回 react-dom@17.0.2
和 react@17.0.2
。
未在类组件、事件处理程序、useMemo、useReducer 或 useEffect 中调用。
我做错了什么? CodeSandbox
// useBooksFetch.js
export const useBooksFetch = (initialUrl, initialData) =>
const [url, setUrl] = useState(initialUrl);
const [data, setData] = useState(initialData);
const [isLoading, setIsLoading] = useState(false);
const [isError, setIsError] = useState(false);
useEffect(() =>
const fetchBooks = async () =>
setIsError(false);
setIsLoading(true);
try
const result = await axios(url);
setData(result.data);
catch (isError)
setIsError(true);
setIsLoading(false);
;
fetchBooks();
, [url]);
return [ data, isLoading, isError , setUrl];
;
// useBooksFetch.test.js
const server = setupServer(
rest.get(
"https://www.googleapis.com/books/v1/volumes?q=travel",
(req, res, ctx) =>
return res(
ctx.status(200),
ctx.json(
data:
items: [
volumeInfo:
title: "Travels"
,
volumeInfo:
title: "The Travel Book"
,
volumeInfo:
title: "Two Arabic Travel Books"
,
volumeInfo:
title: "Around India in 80 Trains"
,
volumeInfo:
title: "World Travel"
,
volumeInfo:
title:
"The ‘Book’ of Travels: Genre, Ethnology, and Pilgrimage, 1250-1700"
,
volumeInfo:
title: "The Impossible Collection of Chinese Art"
,
volumeInfo:
title: "Travel Home"
,
volumeInfo:
title: "Maximum City"
,
volumeInfo:
title: "The Art of Travel"
]
)
);
)
);
beforeAll(() => server.listen());
afterAll(() => server.close());
afterEach(() => server.resetHandlers());
it("fetches successfully", async () =>
const result = await useBooksFetch();
expect(result.data).toHaveLength(10);
);
【问题讨论】:
【参考方案1】:错误是正确的,你不能在组件之外使用钩子。
例如使用这个库https://github.com/testing-library/react-hooks-testing-library
【讨论】:
以上是关于如何使用 Mock Service Worker 在自定义钩子中模拟获取?的主要内容,如果未能解决你的问题,请参考以下文章
使用 mock service worker 测试 React App 时如何记录请求数?
Jest 使用 Mock Service Worker (MSW) 或其他模拟离线网络?
当我使用 Mock Service Worker 测试两个 get 请求时,为啥 req.url.searchParams 参数对象为空?
如何通过 cdn 脚本注册 service worker。如何使用外部 url 注册 service worker