[英]Mocking a promise inside useEffect with CRA, React Testing Library and Jest
I am having an issue mocking a returned Promise
using:我有一个问题 mocking 返回
Promise
使用:
I have a file:我有一个文件:
const books = [{
id: 1,
name: 'book'
}];
export const getBooks = () =>
new Promise((res) => res(books));
I have a useEffect
in my app:我的应用程序中有一个
useEffect
:
export const App = () => {
const [books, setBooks] = useState(undefined);
useEffect(() => {
const fetchData = async () => {
try {
const response = await getBooks();
setBooks(response);
} catch (error) {
setError("There seems to be an issue. Error:", error);
}
};
fetchData();
}, []);
return (
<div>
{books &&
books.map((book) => {
return (
<li key={book.id}>
{book.name}
</li>
);
})
}
</div>
I have a test:我有一个测试:
import { App } from './App';
import { getBooks } from './books';
jest.mock('./books', () => ({
getBooks: jest.fn(),
}));
getBlocks.mockReturnValue(() => Promise.resolve([{
id: 1,
name: 'mock book'
}]));
describe('App', () => {
it('should render blocks', async () => {
await render(<App />);
expect(screen.getByText('mock book')).toBeInTheDocument();
});
});
I just can't mock the return value!我只是不能嘲笑返回值! I can assert it's been called and I can console log the
getBooks
to see that it's mocked I just can't get any results.我可以断言它已被调用并且我可以控制台记录
getBooks
以查看它是否被模拟我只是无法获得任何结果。 I also want to reject it so I can test the unhappy path but it won't work.我也想拒绝它,这样我就可以测试不愉快的路径,但它不会起作用。 Any ideas?
有任何想法吗?
Few things:一些事情:
getBlocks
but getBooks
.getBlocks
而是getBooks
。await
keyword is not necessary before rendering the component with render
.render
渲染组件之前不需要await
关键字。getBooks
returns a promise that resolves with the value of books
, yet when you're trying to mock it, you are making it return a function that returns a promise. Very different things. getBooks
返回一个 promise,它用books
的值解析,但是当你试图模拟它时,你正在让它返回一个function ,它返回一个 promise。非常不同的东西。getBooks
on each one of your tests, you can move it inside a beforeEach
hook.getBooks
的模拟值,则可以将它移动到beforeEach
挂钩中。 You can always override it for a specific test in which you are testing some edge case (eg an exception being thrown by the function, AKA "Unhappy path").books
will be undefined
, so you need to wait for the state to be updated.books
将是undefined
,因此您需要等待 state 更新。 getByText
query won't work, since it will immediately throw an error because it won't find the text you're expecting. getByText
查询将不起作用,因为它会立即抛出错误,因为它找不到您期望的文本。 You need to use the findByText
query for this.findByText
查询。 It returns a promise that resolves when an element that matches the given query is found and rejects if the element is not found after the default timeout of 1000ms.getBooks
returns a promise, it makes more sense to use mockResolvedValue
instead of mockReturnValue
.getBooks
返回 promise,因此使用mockResolvedValue
而不是mockReturnValue
更有意义。import { render, screen } from "@testing-library/react"
import { App } from "./App"
import { getBooks } from "./books"
jest.mock("./books", () => ({
getBooks: jest.fn()
}))
describe("App", () => {
it("should render blocks", async () => {
getBooks.mockResolvedValueOnce([{ id: 1, name: "mock book" }])
render(<App />)
expect(await screen.findByText("mock book")).toBeInTheDocument()
})
})
Try this:尝试这个:
jest.mock('./books', () => ({
getBooks: jest.fn().mockReturnValue(() => Promise.resolve([{
id: 1,
name: 'mock book'
}]));
}));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.