【发布时间】:2019-11-26 11:54:02
【问题描述】:
我正在测试一个具有提交按钮的功能组件,该按钮可以对 api 进行异步调用。异步调用位于自定义挂钩中。根据标准测试实践,我已经模拟了钩子,因此我的模拟将被调用而不是实际的异步 api:
someComponent.test.js
jest.mock("../../../CustomHooks/user", () => ({
useUser: () => ({
error: null,
loading: false,
forgotPassword: <SOMETHING HERE>
})
}));
我知道我的 forgotPassword 函数被调用,因为当我将其更改为 forgotPassword: "" 时,我在测试中收到错误,指出 forgotPassword 不是函数。
单击提交按钮时调用的函数的一个非常简单的表示是这样的:
someComponent.js
import { useUser } from "../../../CustomHooks/user"
const SomeComponent = () => {
....state and other things etc....
const { error, loading, forgotPassword } = useUser()
const submit = async () => {
await forgotPassword(emailValue);
setState(prevState => {
return {
...prevState,
content: "code"
};
});
}
}
注意:我对异步函数 await forgotPassword... 的调用包含在代码中的 try/catch 块中,但为了清楚起见,我将其省略了。
在生产中,当提交按钮被按下时,会发生异步调用,然后应该切换状态,从而渲染一些其他组件。我的测试查看这些组件是否已被渲染(我为此使用了反应测试库)。
我遇到的问题是,无论我在第一个代码块的占位符中放置什么,我的测试总是会失败,因为永远不会到达 setState 块。如果我删除 await 语句,那么 setState 块会被击中,并且我想要出现的组件在状态发生变化时就在那里。但是,显然这在测试之外不会按预期工作,因为实际调用是异步的。以下是我尝试过的一些不起作用的方法:
DOESN'T WORK
forgotPassword: () => {
return Promise.resolve({ data: {} });
}
DOESN'T WORK
forgotPassword: jest.fn(() => {
return Promise.resolve();
})
DOESN'T WORK
forgotPassword: jest.fn(email => {
return new Promise((resolve, reject) => {
if (email) {
resolve(email);
} else {
reject("Error");
}
});
}),
正如我已经说过的,如果我删除 await 语句,那么状态会发生变化并且组件会出现,因此测试通过。但是,由于显而易见的原因,这不是我想要的。
额外信息
这是我的测试的简化版本:
it("changes state/content from email to code when submit clicked", () => {
const { getByTestId, getByText, debug } = render(<RENDER THE COMPONENT>);
const submitButton = getByTestId("fpwSubmitButton");
expect(submitButton).toBeInTheDocument();
const emailInput = getByTestId("fpwEmailInput");
fireEvent.change(emailInput, {
target: { value: "testemail@testemail.com" }
});
fireEvent.click(submitButton);
debug();
THE STATEMENTS BELOW ARE WHERE IT FAILS AS THE STATE DOESN'T CHANGE WHEN AWAIT IS PRESENT
const codeInput = getByTestId("CodeInput");
expect(codeInput).toBeInTheDocument();
});
【问题讨论】:
标签: reactjs unit-testing testing async-await jestjs