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

Posted

技术标签:

【中文标题】如何为每个测试模拟不同的 useLocation 值?【英文标题】:How to mock different value, of useLocation, for each test? 【发布时间】:2020-08-10 00:07:06 【问题描述】:

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

有自定义钩子,在组件加载时调用。 在钩子中有一个useLocation().pathname 的检查和正确更改的开关/大小写结果。

这可以在一个文件/描述中进行 Jest 测试吗? 我试过jest.mockuseLocation,但我无法在 Jest describe 中做到这一点......

这是模拟,目前不在描述中 - 这有效,但不能在测试之间更改:

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

如何测试所有的 switch/case 分支?

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

【问题讨论】:

【参考方案1】:

最简单的方法是使用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);
);

【讨论】:

【参考方案2】:

为了摆脱@skyboyer 的回答,我使用renderHook 得到了很好的效果

第一个参数是您要测试的钩子,第二个参数是您的包装器,我将 &lt;MemoryRouter&gt;&lt;Route&gt; 包装在 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');
  );

【讨论】:

以上是关于如何为每个测试模拟不同的 useLocation 值?的主要内容,如果未能解决你的问题,请参考以下文章

如何为测试目的模拟网络故障(在 C# 中)?

Azure DevOps:如何为不同的测试(.net core、angular)合并两个代码覆盖率报告

K6 负载测试 - 如何为整个测试运行创建顺序 ID

如何为 Android Studio 创建小米模拟器?或者任何其他方式在小米模拟器上测试应用程序?

Angular:如何为 Angular 应用程序中的功能创建测试模块?

如何为 GWT servlet 编写测试?