用 jsodom 和 jest 测试 react-mapbox-gl

Posted

技术标签:

【中文标题】用 jsodom 和 jest 测试 react-mapbox-gl【英文标题】:Testing a react-mapbox-gl with jsodom and jest 【发布时间】:2018-07-29 16:24:17 【问题描述】:

假设我们有以下 Map 组件。这是在 TypeScript 中,但同样适用于普通的 javascript

import * as React from 'react';
import ReactMapboxGl from 'react-mapbox-gl';

const MapBox = ReactMapboxGl(
  accessToken: 'pk.<redacted>'
);

export default class Map extends React.Component 
  render() 
    return (
      <MapBox
        style="mapbox://styles/mapbox/streets-v9"
        zoom=[0]
        containerStyle=
          height: '500px',
          width: 'inherit'
        
      />);
  

它是一些反应应用程序的一部分,被渲染成这样:

import * as React from 'react';

export default class App extends React.Component 
  render() 
    return (
          <Map />
    );
  

为了测试这个设置,我们使用 Jest 和 JSDOM。

import * as React from 'react';
import * as ReactDOM from 'react-dom';
import App from './App';

it('renders without crashing', () => 
  const div = document.createElement('div');
  ReactDOM.render(<App />, div);
);

此测试将无法运行并产生以下输出:

    TypeError: window.URL.createObjectURL is not a function

      at Object.254.../../source/worker (node_modules/mapbox-gl/dist/mapbox-gl.js:509:100)
      at s (node_modules/mapbox-gl/dist/mapbox-gl.js:1:711)
      at node_modules/mapbox-gl/dist/mapbox-gl.js:1:762
      at Object.280.../ (node_modules/mapbox-gl/dist/mapbox-gl.js:561:28)
      at s (node_modules/mapbox-gl/dist/mapbox-gl.js:1:711)
      at node_modules/mapbox-gl/dist/mapbox-gl.js:1:762
      at Object.263../worker_pool (node_modules/mapbox-gl/dist/mapbox-gl.js:527:29)
      at s (node_modules/mapbox-gl/dist/mapbox-gl.js:1:711)
      at node_modules/mapbox-gl/dist/mapbox-gl.js:1:762
      at Object.191.../render/glyph_manager (node_modules/mapbox-gl/dist/mapbox-gl.js:383:809)
      at s (node_modules/mapbox-gl/dist/mapbox-gl.js:1:711)
      at node_modules/mapbox-gl/dist/mapbox-gl.js:1:762
      at Object.248.../geo/lng_lat (node_modules/mapbox-gl/dist/mapbox-gl.js:497:338)
      at s (node_modules/mapbox-gl/dist/mapbox-gl.js:1:711)
      at node_modules/mapbox-gl/dist/mapbox-gl.js:1:762
      at Object.72.../package.json (node_modules/mapbox-gl/dist/mapbox-gl.js:144:148)
      at s (node_modules/mapbox-gl/dist/mapbox-gl.js:1:711)
      at e (node_modules/mapbox-gl/dist/mapbox-gl.js:1:882)
      at node_modules/mapbox-gl/dist/mapbox-gl.js:1:900
      at Object.<anonymous>.i (node_modules/mapbox-gl/dist/mapbox-gl.js:1:177)
      at Object.<anonymous> (node_modules/mapbox-gl/dist/mapbox-gl.js:1:413)
      at Object.<anonymous> (node_modules/react-mapbox-gl/lib/map.js:21:16)
      at Object.<anonymous> (node_modules/react-mapbox-gl/lib/index.js:3:13)
      at Object.<anonymous> (src/Map.tsx:14:25)
      at Object.<anonymous> (src/NewOrder.tsx:21:13)
      at Object.<anonymous> (src/Routes.ts:17:18)
      at Object.<anonymous> (src/App.tsx:16:16)
      at Object.<anonymous> (src/App.test.tsx:6:169)
          at <anonymous>

亲爱的读者,您的问题很简单:是否有可能解决这个问题?我们可以使用接缝来注入模拟的 MapBoxGL 库吗?

我在 GitHub 上发现了多个与此问题相关的问题,但没有一个提供解决方案:1、2。使用mapbox-gl-js-mock 的一些观点,而另一些则声称它没有用,因为它也需要真正的浏览器才能运行。

在 JSDOM 项目中还有 related issue 关于添加 URL.createObjectURL 可能会解决根本问题。

【问题讨论】:

【参考方案1】:

如果您使用的是 import 和 typescript:

jest.mock('mapbox-gl/dist/mapbox-gl', () => 
  return 
    'default': 
      accessToken: '',
      GeolocateControl: jest.fn(),
      Map: jest.fn(() => (
        addControl: jest.fn(),
        on: jest.fn(),
        remove: jest.fn(),
        fitBounds: jest.fn(),
      )),
      NavigationControl: jest.fn(),
    
  
);

【讨论】:

应该可以解决这个问题吗? github.com/visgl/react-map-gl/issues/1478【参考方案2】:

您可以将此添加到setupTest.ts 的测试条目文件中

jest.mock('mapbox-gl/dist/mapbox-gl', () => (
  GeolocateControl: jest.fn(),
  Map: jest.fn(() => (
    addControl: jest.fn(),
    on: jest.fn(),
    remove: jest.fn(),
  )),
  NavigationControl: jest.fn(),
));

【讨论】:

【参考方案3】:

我遇到了同样的问题,当我将here 列出的以下代码添加到我的测试块的顶部时,它起作用了。

jest.mock('mapbox-gl/dist/mapbox-gl', () => (
   Map: () => ()
));

【讨论】:

This issue 也是相关的。特别是,在我有一个工作设置之前,我必须走得更远(正如this comment 建议的那样)。

以上是关于用 jsodom 和 jest 测试 react-mapbox-gl的主要内容,如果未能解决你的问题,请参考以下文章

用 Jest 和 Enzyme 测试 React Router

用 Jest 测试 React 应用程序:意外的令牌

React Js API 调用 Jest 测试用例?

用 jest 和 react-testing-library 测试反应上下文

用React Testing Library 和 Jest 完成单元测试

用 Jest 模拟 React 自定义钩子