简体   繁体   English

Mocking a promise inside useEffect with CRA, React Testing Library and Jest

[英]Mocking a promise inside useEffect with CRA, React Testing Library and Jest

I am having an issue mocking a returned Promise using:我有一个问题 mocking 返回Promise使用:

  • Create React app创建 React 应用
  • Jest笑话
  • RTL实时语言

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:一些事情:

  1. You have a typo, it's not getBlocks but getBooks .你打错了,不是getBlocks而是getBooks
  2. The await keyword is not necessary before rendering the component with render .在使用render渲染组件之前不需要await关键字。
  3. 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。非常不同的东西。
  4. You have to move the mocking to the test block in which it'll be used, or if you need this mocked value from getBooks on each one of your tests, you can move it inside a beforeEach hook.您必须将 mocking 移动到将在其中使用它的测试块,或者如果您在每个测试中都需要来自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").您始终可以针对正在测试某些边缘情况的特定测试覆盖它(例如,function 抛出的异常,也称为“不快乐路径”)。
  5. On the component's first render, 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.它返回一个 promise,当找到与给定查询匹配的元素时解析,如果在默认超时 1000 毫秒后未找到该元素,则拒绝。
  6. Since 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.

相关问题 Mocking Jest 中的 React 上下文提供程序与 react-testing-library - Mocking React context provider in Jest with react-testing-library 使用 React 测试库/Jest 模拟 axios 帖子 - Mocking an axios post using React Testing Library / Jest 使用 Jest 和 React-Testing-Library 模拟 Context .Provider 的数据 - Mocking data for a Context .Provider with Jest and React-Testing-Library 使用 Jest 和 React 进行单元测试 - Axios 了解 useEffect - Unit Testing with Jest and React - Axios Get Inside useEffect 在 React/Jest 中测试/模拟功能容器内的服务 - Testing/mocking a service inside functional container in React/Jest 使用 react-testing-library 在 useEffect 中测试 api 调用 - Testing api call inside useEffect using react-testing-library 开玩笑的测试库 - 模拟拒绝承诺在 useAsync() 中没有按预期工作 - jest testing library - mocking reject promise not working as expected for function within useAsync() 开玩笑地测试以更新被拒绝的 promise 中的反应 state - testing with jest to update a react state inside a rejected promise React testing-library - 测试在第一个 useEffect 挂钩中设置状态的 promise - React testing-library - Testing a promise that set states in the first useEffect hook useEffect 中的回调不在 JEST 测试中执行? - callback inside useEffect not executing in JEST testing?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM