使用 react-testing-library 在 Jest 中模拟 React 上下文提供程序

Posted

技术标签:

【中文标题】使用 react-testing-library 在 Jest 中模拟 React 上下文提供程序【英文标题】:Mocking React context provider in Jest with react-testing-library 【发布时间】:2021-01-24 02:48:24 【问题描述】:

我有一个相当复杂的上下文,我将其包裹在我的应用程序中以处理身份验证并提供从身份验证服务检索到的相关数据。我想绕过提供者的所有功能,只是模拟一个返回值。当上下文呈现时,它会执行一堆我在测试时不希望发生的初始化函数。

我在包装函数中尝试过这样的事情:

const mockValue = 
  error: null,
  isAuthenticated: true,
  currentUser: 'phony',
  login: jest.fn(),
  logout: jest.fn(),
  getAccessToken: jest.fn(),


const MockAuthContext = () => ( React.createContext(mockValue) )

jest.mock("../contexts/AuthContext", () => (
  __esModule: true,
  namedExport: jest.fn(),
  default: jest.fn(),
));

beforeAll(() => 
  AuthContext.mockImplementation(MockAuthContext);
);

const customRender = (ui,  ...renderOpts  = ) => 
  const ProviderWrapper = ( children ) => (
      <AuthContext.Provider>
         children
      </AuthContext.Provider>
  );
  return render(ui,  wrapper: ProviderWrapper, ...renderOpts );
;

// re-export everything
export * from "@testing-library/react";

// override render method
export  customRender as render ;

唉,我得到一个错误: Error: Uncaught [Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.

事实上,如果我记录 Provider 呈现的内容,我会得到:

    
      '$$typeof': Symbol(react.element),
      type: undefined,
      ...

我尝试将提供程序设置为 AuthContext.getMockImplementation().Provider。没有骰子。

无论如何,有人看到我在这里要完成的工作吗?我只想模拟整个上下文,以便组件只获得一个返回已知值而不执行任何上下文代码的提供程序。 react-testing-library 和 Jest 有可能吗?

【问题讨论】:

什么是 AuthContext 以及为什么需要模拟它?这可能是 XY 问题。通常不需要模拟提供程序,因为可以使用 value 传递新值。 所以,我想我并不清楚我要避免的是在提供程序中执行一堆代码。当它挂载时,会发生一系列配置和验证数据检查。我想在测试时将所有这些都短路,以便它只是愚蠢地返回我在value 中给出的内容。我认为我想出了一个不错的技巧来在 Provider 组件上设置一个 testMode 标志道具,这样它就只返回值(以及相关的模拟 jest.fn() 的)并忽略Provider 初始化的其余部分。事实证明,如果我这样做,我不需要模拟上下文本身。 【参考方案1】:

错误表示AuthContext.Provider 不是 React 组件。 AuthContext 是 Jest 间谍,即一个函数,它没有 Provider 属性。因为AuthContext 应该是 React 上下文,所以应该这样定义。对于默认导出,它应该是:

jest.mock("../contexts/AuthContext", () => (
  __esModule: true,
  default: React.createContext()
));

然后可以在测试中提供任何模拟值:

<AuthContext.Provider value=mockValue>

【讨论】:

啊,少了些hacky。谢谢,我已经准备好了,但出于教育目的,我稍后会试一试。谢谢!

以上是关于使用 react-testing-library 在 Jest 中模拟 React 上下文提供程序的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 React-Testing-Library 测试 mapDispatchToProps?

如何使用 Jest 和 react-testing-library 测试 useRef?

react-testing-library - 屏幕与渲染查询

如何使用 react-testing-library 测试由其他组件组成的组件?

使用 react-testing-library 时如何测试组件是不是使用正确的道具呈现?

使用 react-testing-library 时找不到带有文本的元素:“myText”错误