如何为每个测试模拟useLocation的不同值?

时间:2020-04-26 13:49:51

标签: jestjs react-hooks react-router-dom react-component

我的react组件应该根据当前位置对状态进行一些更改。

有一个自定义钩子,在组件加载时被调用。 在挂钩中检查useLocation().pathname,并在switch / case中检查结果是否正确。

可以在一个文件/描述中对Jest进行测试吗? 我尝试jest.mock useLocation,但在Jest描述中只是做不到...

这是模拟,目前不在描述范围内,并且可以使用,但是不能在测试之间更改:

const mockUseLocation = () => {
    jest.mock('react-router-dom', () => ({
        useLocation: jest.fn().mockReturnValue({
            pathname: '/val1'
        })
    }))
};

如何测试所有开关/案例分支?

switch (pathname) {
   case 'val1':
       return 100;
   case 'val2':
       return 200;
   ...
   ...
}

2 个答案:

答案 0 :(得分:1)

为了结束@skyboyer 的回答,我使用 renderHook

第一个参数是您要测试的钩子,第二个参数是您的包装器,我将 <MemoryRouter>, <Route> 包裹在 children 道具周围。

// test.js
import React, { FC } from 'react';
import { MemoryRouter, Route } from 'react-router-dom';
import { renderHook } from '@testing-library/react-hooks';

it('returns value from url query', () => {

    const wrapper: FC = ({ children }) => (
      <MemoryRouter initialEntries={[`/?user=authorized`]}>
        <Route path="*" />
        {children}
      </MemoryRouter>
    );
    
    const { result } = renderHook(() => useLocation(), { wrapper });

    expect(result.current).toBe('authorized');
  });

答案 1 :(得分:0)

最简单的方法是使用MemoryRouter代替模拟useLocation。如果您的组件具有<Link>,这也将很有帮助(否则您将收到错误“无法在路由器外部使用链接”)。此外,它还允许您检查导航是否发生。因此,具有如此多的好处,直接模拟useLocation没有任何价值。

在正式文档中加入look into examples。会是一样的东西:

test("current user is active in sidebar", () => {
  const wrapper = mount(
    <MemoryRouter initialEntries={["/users/2"]}>
      <YourComp />
    </MemoryRouter>
  );
  expected(wrapper.find(User)).toHaveLength(2);
});