javascript - Jest 如何模拟 API 调用的实现
问题描述
如标题中所述,我试图模拟一个函数的实现。我是测试 React 应用程序的新手。我一直在互联网上寻找如何实现我的目标的几个小时,所以让我解释一下。
我已经将 API 调用移至另一个文件 (/utils/fetchGetCard.js):
export const fetchGetCard = (lang, word) => {
return fetch("/getCard", {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ lang: lang, word: word })
}).then(response => response.text())
}
然后我在 SearchCard.jsx 中有一个功能组件:
const searchCard = (event) => {
event.preventDefault();
event.stopPropagation();
if (event.currentTarget.checkValidity() === true) {
setValidated(false);
fetchGetCard(selectInput.current.value, wordInput.current.value)
.then(data => {
if (data === "ERR") {
console.log("Oops, something went wrong!");
} else if (data === "MISSING_WORD") {
console.log("Somehow your word wasn't passed to the backend");
} else {
if (data === '') {
showModal(wordInput.current.value);
} else {
setCardInfo(JSON.parse(data));
setCardLang(selectInput.current.value);
setFound(true);
}
}
}).catch((error) => {
console.error('Error:', error);
})
} else {
setValidated(true);
}
}
searchCard 函数与 Form 组件的 onSubmit 相关联(来自 react-bootstrap)。现在我想进行一个测试,在其中渲染组件,然后输入一些信息并按下按钮。在这一部分中,我可能想模拟 API 调用以返回正确的硬编码数据。最后,我想检查是否呈现了新组件(基于 API 数据)。这是我到目前为止所拥有的:
import SearchCard from './SearchCard.jsx';
import { render, waitFor } from '@testing-library/react';
import { fireEvent, screen } from "@testing-library/dom";
import { fetchGetCard } from "../utils/fetchGetCard.js";
jest.mock("../utils/fetchGetCard.js");
test("render SearchCard when card has been found", async () => {
fetchGetCard.mockImplementation(() => {
`{
"word": "hund",
"pronounciation": "ˈhʉn",
"translation": [
{
"type": "noun",
"meaning": "Its a dog mkay?",
"grammarNoun": {
"countable": "true",
"gender": "masculine",
"singularIndefinite": "en hund",
"singularDefinite": "hunden",
"pluralIndefinite": "hunder",
"pluralDefinite": "hundene"
}
}
]
}`
});
render(<SearchCard />);
const testWordInput = screen.getByTestId("testWordInput");
testWordInput.innerHTML = "hund";
const testButtonSearch = screen.getByTestId("testButtonSearch");
fireEvent.click(testButtonSearch);
expect(fetchGetCard).toHaveBeenCalled();
await waitFor(() => screen.findByTestId("testFoundCard"));
expect(screen.getByText("hʉn")).toBeInTheDocument();
});
任何指导将不胜感激!
编辑 1: 将 testWordInput.innerHTML 更改为 testWordInput.value 修复了它,看来我已经成功地模拟了 fetchGetCard 函数。不过,似乎 setCardInfo()、setCardLang() 和 setFound()(可能所有的 setter)都不起作用。这些方法来自 useState 钩子。他们应该工作得很好还是我可以做些什么来改变状态?
解决方案
修复了问题:如编辑中所述,我设法从expect(fetchGetCard).toHaveBeenCalled()
. 最后一件事是我的错,实际上我没有将“testFoundCard”ID分配给DOM中的任何东西,我最终得到:
await waitFor(() => expect(screen.getByText("hundene")).toBeInTheDocument());
现在它起作用了!
推荐阅读
- python - 如何使用来自 3 列 numpy 数组(gpname,x,y)的组创建二维散点图?
- java - 如何实现 onPause() 和 onResume?
- php - Sylius:资源创建了哪些路由?
- c++ - 使用 C++ 扩展 Python/Numpy,模块在初始化时崩溃
- monitoring - 从访问日志中存储响应时间和 influxdb 中的请求数
- php - 为 PHP-C++ 项目安装 Composer
- python - 优化 Python 代码以量化浮点数序列
- neo4j - 如何阻止 Neo4J Cypher 处理空集合?
- html - 需要 HTML5 表单输入 - 使用 Canvas
- r - R:一次grep多个字符串