【问题标题】:How to use react-testing-library and jest with mocked custom react hook updating?如何使用 react-testing-library 和 jest 来模拟自定义反应钩子更新?
【发布时间】:2021-10-10 02:13:24
【问题描述】:

看看下面的自定义钩子。前提是当query发生变化时,它会更新自己的状态。

export function UseCustomHook() {
  const { query } = useRouter()
  const [state, setState] = useState({})

  useEffect(() => {
    const updatedState = helperFunction(query)
    setState(updatedState)
  }, [query])

  return state
}

目标是模拟useRouter,然后对其进行更新以专门测试“当查询更新 n 次时,辅助函数被调用 n 次”

我们可以模拟模块useRouter

jest.mock('next/router', () => ({
  useRouter() {
    return {
      route: '/',
      pathname: '',
      query: {...},
      asPath: '',
    }
  },
}))

但这只是将其模拟为普通模块。我想把它模拟成一个钩子,然后在下面的测试中更新它

describe('useCustomHook', () => {
    it('should call helperFunction when query updates', () => {
        const query = {...}
        jest.spyOn(Router, 'useRouter' as any).mockImplementation(() => ({ query }))
        
        const { result } = renderHook(() => useCustomHook())
        expect(...)  
    })
  })
  

【问题讨论】:

    标签: reactjs unit-testing jestjs react-hooks react-hooks-testing-library


    【解决方案1】:

    您可以使用jest.mock() 模拟next/router 模块、useRouter 钩子及其返回值。在我们更改了query 的值之后,我们应该调用rerender 函数来重新渲染自定义钩子,这样useEffect 钩子就会使用新的query 作为它的依赖。

    另外,我使用jest.spyOn()console.count()方法上添加spy来检查effect函数调用了多少次。

    例如

    useCustomHook.ts:

    import { useRouter } from 'next/router';
    import { useEffect, useState } from 'react';
    
    export function useCustomHook() {
      const { query } = useRouter();
      const [state, setState] = useState({});
    
      useEffect(() => {
        console.count('effect');
        setState({ id: query.id });
      }, [query]);
    
      return state;
    }
    

    useCustomHook.test.ts:

    import { useRouter } from 'next/router';
    import { renderHook } from '@testing-library/react-hooks';
    import { useCustomHook } from './useCustomHook';
    import { mocked } from 'ts-jest/utils';
    import { NextRouter } from 'next/dist/next-server/lib/router/router';
    
    jest.mock('next/router');
    
    const useMockRouter = mocked(useRouter);
    
    describe('68660313', () => {
      test('should pass', () => {
        const countSpy = jest.spyOn(console, 'count');
        const query1 = ({ query: { id: '1' } } as unknown) as NextRouter;
        const query2 = ({ query: { id: '2' } } as unknown) as NextRouter;
    
        useMockRouter.mockReturnValue(query1);
        const { result, rerender } = renderHook(() => useCustomHook());
        expect(result.current).toEqual({ id: '1' });
        useMockRouter.mockReturnValue(query2);
        rerender();
        expect(result.current).toEqual({ id: '2' });
        expect(countSpy).toBeCalledTimes(2);
      });
    });
    

    测试结果:

     PASS  examples/68660313/useCustomHook.test.ts (7.664 s)
      68660313
        ✓ should pass (32 ms)
    
      console.count
        effect: 1
    
          at console.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
    
      console.count
        effect: 2
    
          at console.<anonymous> (node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866:25)
    
    ------------------|---------|----------|---------|---------|-------------------
    File              | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    ------------------|---------|----------|---------|---------|-------------------
    All files         |     100 |      100 |     100 |     100 |                   
     useCustomHook.ts |     100 |      100 |     100 |     100 |                   
    ------------------|---------|----------|---------|---------|-------------------
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        8.184 s
    

    包的版本:

    "next": "^11.0.1",
    "jest": "^26.6.3",
    "ts-jest": "^26.4.4",
    "react": "^16.14.0",
    

    【讨论】:

      猜你喜欢
      • 2021-04-25
      • 1970-01-01
      • 2023-03-17
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2022-08-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多