【问题标题】:Mocking library hook with Jest用 Jest 模拟库钩子
【发布时间】:2021-05-11 07:06:33
【问题描述】:

设置

我在我的一个组件中使用了一个名为 react-firebase-hooks 的库。

// Component.tsx
import React, {useEffect} from 'react';
import { Firebase } from '../firebase/firebase';
import { useAuthState } from 'react-firebase-hooks/auth';


export const Component = () => {
  // Note that Firebase.getAuth is a static method of a class of mine for getting the firebase authentication object
  const [user, loading ] = useAuthState(Firebase.getAuth());


  if (!loading && !user) {
    // ... stuff
  }

  return (
    <div>

      ...stuff
    </div>
  );
};

一种有效的方式

我试图在我的一项测试中模拟出useAuthState 调用,但在找出执行模拟的最佳方法时遇到了很多麻烦。我找到了一个可行的解决方案:

// Component.test.tsx
import {useAuthState} from 'react-firebase-hooks/auth'

jest.mock('react-firebase-hooks/auth', () => ({
  useAuthState: jest.fn()
}));

但是,上面的模拟实现使得模拟对象无法在 IDE 中完成。例如,这是我尝试设置一个模拟返回值:

      test(`component correctly loads`, () => {
         useAuthState.mockReturnValue([true, false])

        // renderApp is a utility method of mine to render using react-testing-library
        const { getByText } = renderApp();

        // expect some stuff
      });

我的首选结果(和尝试 1)

我发现useAuthState 没有自动完成功能。

理想情况下,我希望声明模拟的方式更接近

const mockAuth = jest.fn();
jest.mock('react-firebase-hooks/auth', () => {
  return jest.fn().mockImplementation(() => {
    return {useAuthState: mockAuth}
  })
});

然后让我通过我声明的测试(并获得自动完成)很好地改变 mockAuth 对象,例如:

      test(`component correctly loads`, () => {
         mockAuth.mockReturnValue([true, false])

        // renderApp is a utility method of mine to render using react-testing-library which renders Component
        const { getByText } = renderApp();

        // expect some stuff
      });

但是,通过上述实现,我收到以下错误:(0 , _auth.useAuthState) is not a function or its return value is not iterable in Component

尝试 2

我也尝试过将模拟声明为

const mockAuth = jest.fn();
jest.mock('react-firebase-hooks/auth', () => ({
    useAuthState: mockAuth
}));

但这给了我ReferenceError: Cannot access 'mockAuth' before initialization的错误。

尝试 3

我也试过

const mockAuth = jest.fn();
import {useAuthState} from 'react-firebase-hooks/auth'
jest.mock('react-firebase-hooks/auth', () => ({
    useAuthState: mockAuth
}));

但这给出了同样的错误。

结束问题

有没有办法让我在模拟声明的“外部”声明一个模拟函数,以便我可以自动完成它?

【问题讨论】:

标签: reactjs typescript firebase jestjs


【解决方案1】:

如果您使用另一个文件进行模拟,您应该很容易更改实现并仍然保留 TypeScript Intellisense。

src/App.test.jsx

import App from "../App";
import { render } from "@testing-library/react";
import { useAuthState } from "../__mocks__/react-firebase-hooks/auth";

it("should be mocked", () => {
  // Change the implementation of the mock
  useAuthState.mockReturnValue([true, false]);
  const { getByText } = render(<App />);
  // Expect that the app file got the mocked value
  expect(useAuthState).toBeCalledWith("my auth");
  expect(getByText("true,false")).toBeTruthy();
});

src/__mocks__/react-firebase-hooks/auth.js

export const useAuthState = jest.fn();

src/App.js

import { useAuthState } from "react-firebase-hooks/auth";

export default function App() {
  const test = useAuthState("my auth");
  return <div>{test.toString()}</div>;
}

【讨论】:

  • 哇,太酷了。我以前没有见过这种语法。你有没有我可以阅读的文档的链接?这是模拟的首选方式吗?这种方法有什么缺点?
  • 我能想到的唯一缺点是必须制作一个单独的文件。有时这是理想的,有时它有点烦人。这是相关的文档(尽管在这个特定模型上很少)jestjs.io/docs/en/manual-mocks
猜你喜欢
  • 1970-01-01
  • 2020-03-11
  • 1970-01-01
  • 1970-01-01
  • 2021-04-17
  • 1970-01-01
  • 2022-06-17
  • 2020-10-03
  • 2021-12-03
相关资源
最近更新 更多