用 Jest 模拟库钩子

时间:2021-02-07 13:51:51

标签: reactjs typescript firebase jestjs

设置

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

djongo/pyvenv.cfg

djongo/bin:
activate       activate.ps1      chardetect       easy_install      ndg_httpclient  pip-3.7      python     sqlformat  wheel-3.7
activate.csh   activate_this.py  django-admin     easy_install3     pip             pip3.7       python3    wheel
activate.fish  activate.xsh      django-admin.py  easy_install-3.7  pip3            __pycache__  python3.7  wheel3

djongo/lib:
python3.7

有效的方法

我试图在我的一项测试中模拟 // 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

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

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

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

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

我发现 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 }); 上没有自动完成功能。

理想情况下,我想如何声明模拟将更接近

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

尝试 2

我也尝试将模拟声明为

Component

但这给了我 const mockAuth = jest.fn(); jest.mock('react-firebase-hooks/auth', () => ({ useAuthState: mockAuth })); 的错误。

尝试 3

我也试过

ReferenceError: Cannot access 'mockAuth' before initialization

但这给出了同样的错误。

结束问题

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

1 个答案:

答案 0 :(得分: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>;
}