Reactjs 如何测试使用自定义TypeScript React钩子的组件?

Reactjs 如何测试使用自定义TypeScript React钩子的组件?,reactjs,typescript,jestjs,axios,react-hooks,Reactjs,Typescript,Jestjs,Axios,React Hooks,我目前正在用Typescript编写一个React组件,它使用了一个名为useAxios的钩子。正在使用的此挂钩的一个示例是: export const App=()=>{ 常量[{data,loading,error},refetch]=useAxios( "https://api.myjson.com/bins/820fc" ); 如果(加载)返回加载…; 如果(错误)返回错误!; 返回( refetch()}>refetch {JSON.stringify(数据,null,2)} ); }

我目前正在用Typescript编写一个React组件,它使用了一个名为useAxios的钩子。正在使用的此挂钩的一个示例是:

export const App=()=>{
常量[{data,loading,error},refetch]=useAxios(
"https://api.myjson.com/bins/820fc"
);
如果(加载)返回加载…

; 如果(错误)返回错误!

; 返回( refetch()}>refetch {JSON.stringify(数据,null,2)} ); }; const rootElement=document.getElementById(“根”); render(,rootElement);
我正试图找出如何编写一个可以模拟useAxios钩子的测试。我已尝试创建底层axios组件的模拟,但无法正常工作:

jest.mock('axios-hooks');

import useAxios from 'axios-hooks';

test('App displays loading when request is fetching', () => {
  useAxios.mockReturnValue(Promise.resolve({ loading: true }));
  // mount component
  // Verify "Loading" message is rendered
});
从“React”导入React
从“@testing library/react”导入{render}
从“./Test”导入{Test}
从“axios挂钩”导入useAxios
开玩笑的模仿(“axios钩”)
const mockedAxios=useAxios作为笑话。Mocked
它(“显示加载”,()=>{
//如何模拟下一行中的返回值?
//莫克达克斯。
const{getByText}=render()
expect(getByText(“加载…”)。toBeDefined()
})
我知道我不应该模仿axios,这是底层依赖,我应该能够模仿useAxios,但我想我无论如何都会尝试

我意识到这个问题已经被提到过很多次了,但是我可以找到这个特定用例的解决方案


非常感谢您的帮助

模拟模块并设置每个测试的
useAxios
预期结果,例如

import * as useAxios from "axios-hooks"
jest.mock("axios-hooks")
const mockedAxios = useAxios as jest.Mocked<typeof useAxios>

it("Displays loading message", async () => {

  // Explicitly define what should be returned
  mockedAxios.default.mockImplementation(() => [
      {
        data: [],
        loading: true,
        error: undefined
      },
      () => undefined
    ])

  const { getByText } = render(<Test />)

  expect(getByText("Loading...")).toBeDefined()
})

我自己想出了办法。为了测试自定义挂钩,我执行了以下操作:

import * as useAxios from 'axios-hooks';
import { AxiosPromise } from 'axios';
import React from 'react';
import Test from 'components/Test';
import { render } from '@testing-library/react';

jest.mock('axios-hooks');
const mockedUseAxios = useAxios as jest.Mocked<typeof useAxios>;

it('renders a loading message', async () => {
  mockedUseAxios.default.mockImplementation(() => [
    {
      data: [],
      loading: true,
      error: undefined,
    },
    (): AxiosPromise => (undefined as unknown) as AxiosPromise<unknown>,
  ]);

  const { getByText } = render(<Test />);

  expect(getByText('Loading...')).toBeDefined();
});
import*作为“axios挂钩”中的useAxios
开玩笑的模仿(“axios钩”)
const mockedAxios=useAxios作为笑话。Mocked
它(“显示加载消息”,异步()=>{
//明确定义应该返回的内容
mockedAxios.default.mockImplementation(()=>[
{
数据:[],
加载:对,
错误:未定义
},
()=>未定义
])
const{getByText}=render()
expect(getByText(“加载…”)。toBeDefined()
})

我不得不跳过一些额外的障碍,以使编译器对未定义的
()=>参数感到满意。我不喜欢双重
as
,但我不知道如何让它不那么冗长,因为我是TS新手

import*作为“axios挂钩”中的useAxios;
从“axios”导入{AxiosPromise};
从“React”导入React;
从“组件/测试”导入测试;
从'@testing library/react'导入{render};
开玩笑的模仿(‘axios-hooks’);
const mockedUseAxios=useAxios作为笑话,Mocked;
它('呈现加载消息',异步()=>{
mockedUseAxios.default.mockImplementation(()=>[
{
数据:[],
加载:对,
错误:未定义,
},
():AxiosPromise=>(未定义为未知)作为AxiosPromise,
]);
const{getByText}=render();
expect(getByText('Loading…')).toBeDefined();
});

那么,如果您
jest.mock(“axios挂钩”)
和以后的
useAxious.mockResolvedValue(dataToRespond)
,会发生什么呢?或者您需要基于URL的动态模拟吗?因为我使用的是typescript,所以我似乎无法做到这一点。我假设有一种方法可以使用TS实现这一点,所以问题是特定于TS中的类型检查,对吗?对我来说,它看起来像是测试运行,但mock并没有在这样的事情上工作that@skyboyer我用一个示例测试更新了我的问题。我试图找出如何模拟TS中的钩子返回值。我使用的是TypeScript,但答案似乎并不正确work@BenSmithTS不应该真的进入它,到底什么不起作用?看起来它起作用了。另请参阅我更新的问题,其中有一个不完整的测试是用TS编写的。@BenSmith TS应该是非侵入性的(除非已更改),因此上面的代码应该运行。看看您的示例,您添加了const mockedAxios=useAxios作为jest.Mocked,它将我们带入了TS领域,但这真的有必要吗?你试过没有任何TS的代码了吗?你的答案和我的完全一样,只是返回函数中的变化。你为什么不发表评论呢?我考虑过这一点,但我的回答还包括一个附加的导入语句以及你的示例中缺少的相关导入。我非常感谢您在这里提出这个问题,并为故障排除提供了一个良好的起点。有时候,在一个标记实例中有一个整体合理的方法是很好的。好的,我很高兴我能提供帮助。我经常参考我自己关于嘲笑这个库的答案,因为它每次都会让我发疯!
import * as useAxios from "axios-hooks"
jest.mock("axios-hooks")
const mockedAxios = useAxios as jest.Mocked<typeof useAxios>

it("Displays loading message", async () => {

  // Explicitly define what should be returned
  mockedAxios.default.mockImplementation(() => [
      {
        data: [],
        loading: true,
        error: undefined
      },
      () => undefined
    ])

  const { getByText } = render(<Test />)

  expect(getByText("Loading...")).toBeDefined()
})
import * as useAxios from 'axios-hooks';
import { AxiosPromise } from 'axios';
import React from 'react';
import Test from 'components/Test';
import { render } from '@testing-library/react';

jest.mock('axios-hooks');
const mockedUseAxios = useAxios as jest.Mocked<typeof useAxios>;

it('renders a loading message', async () => {
  mockedUseAxios.default.mockImplementation(() => [
    {
      data: [],
      loading: true,
      error: undefined,
    },
    (): AxiosPromise => (undefined as unknown) as AxiosPromise<unknown>,
  ]);

  const { getByText } = render(<Test />);

  expect(getByText('Loading...')).toBeDefined();
});