【问题标题】:Jest throwing TypeError: Cannot read property 'fetch' of undefined开玩笑抛出 TypeError:无法读取未定义的属性“获取”
【发布时间】:2017-10-18 02:48:22
【问题描述】:

我正在尝试使用 Jest 在我的 react/react-native 库上运行一些测试(里面只有一些业务逻辑)。

我们正在测试使用 fetch 函数的操作(使用 whatwg-fetch 的 polyfill)。 我添加了 whatwg-fetch(感谢 Safari)来进行反应。

每当我尝试运行测试时,我都会收到此错误:

TypeError: Cannot read property 'fetch' of undefined

  at node_modules/whatwg-fetch/fetch.js:4:11
  at Object.<anonymous> (node_modules/whatwg-fetch/fetch.js:461:3)
  at Object.<anonymous> (node_modules/jest-expo/src/setup.js:138:416)

什么会导致这个问题?有没有办法在开玩笑的配置中避免这种情况?

这里有一些用于调试的文件:

package.json 中的 Jest 配置

"jest": {
"preset": "jest-expo",
"moduleFileExtensions": [
  "js",
  "jsx",
  "ts",
  "tsx"
],
"verbose": true,
"transform": {
  "^.+\\.(js|ts|tsx)$": "<rootDir>/node_modules/babel-jest"
},
"testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$",
"testPathIgnorePatterns": [
  "\\.snap$",
  "<rootDir>/node_modules/",
  "<rootDir>/dist/"
],
"transformIgnorePatterns": [
  "node_modules/?!react-native"
]
},

Webpack 配置:

const config = {
entry: [
    'whatwg-fetch',
    __dirname + '/src/index.ts',
],
devtool: 'source-map',
output: {
    path: path.join(__dirname, '/dist'),
    filename: 'index.js',
    library: 'checkinatwork-module',
    libraryTarget: 'umd',
    umdNamedDefine: true,
},
module: {
    loaders: [
        { test: /\.(tsx|ts)?$/, loader: 'ts-loader', exclude: /node_modules/ },
    ],
},
resolve: {
    modules: [
        './src',
        'node_modules',
    ],
    extensions: ['.js', '.ts', '.jsx', '.tsx', 'json'],
},
plugins: [
],
};

测试文件:

import expect from 'expect';
import * as actions from '../../src/components/Checkin/checkin.action';
import * as reducers from '../../src/components/Checkin/checkin.reducer';
import configureMockStore from 'redux-mock-store';
import thunk from 'redux-thunk';
import nock from 'nock';

const middlewares = [ thunk ];
const mockStore = configureMockStore(middlewares);

describe('=> ADD CHECKIN ACTIONS', () => {
  describe('- REQUEST', () => {
    it('Action: ADD_CHECKIN_REQUEST should request addCawCheckin', () => {
      const expectedAction = {
        type: actions.ADD_CHECKIN_REQUEST,
        isFetching: true,
      };
      expect(actions.addCheckinRequest())
        .toEqual(expectedAction);
    });
    it('Reducer: newCheckin should trigger ADD_CHECKIN_REQUEST and initiate loading', () => {
      const expectedState = {
        isFetching: true,
        status: null,
      };
      expect(reducers.newCheckin(reducers.newCheckinDefaultState, actions.addCheckinRequest()))
        .toEqual(expectedState);
    });
  });

动作文件:

export const getCheckins = (sessionId, date, url, isRefresh) => {
  const config = {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({
      sessionId: {sessionId},
      date: {date},
    }),
  };

  return dispatch => {
    if (!isRefresh) {
      dispatch(getCheckinsRequest());
    }
    return fetch(url + 'getCAWCheckIns', config)
      .then(response => response.json())
      .then(({ checkins }) => {
        dispatch(getCheckinsSuccess(checkins));
      }).catch(err => {
        dispatch(getCheckinsError('Get checkins failed'));
        console.error('Get checkins failed: ', err);
      });
  };
};

谢谢!

【问题讨论】:

    标签: reactjs react-native webpack fetch jestjs


    【解决方案1】:

    这对我有用。在需要 whatwg-fetch 的博览会设置文件 (node_modules/jest-expo/src/setup.js) 中,我将要求更改为 require('fetch-everywhere')

    const { Response, Request, Headers, fetch } = 
      require('fetch-everywhere');
    global.Response = Response;
    global.Request = Request;
    global.Headers = Headers;
    global.fetch = fetch;
    

    由于某些原因,只有 fetch 到处都在使用 expo 和 jest。

    【讨论】:

      【解决方案2】:

      将 react-native、jest 和 babel-jest 升级到最新版本为我们解决了这个问题。

      【讨论】:

        【解决方案3】:

        可能会迟到,但这对我有用。

        可能的解决方案#1

        注意:React.PropTypes 自 React v15.5 起已弃用。请改用 prop-types 库。

        如果你安装 npm 包 prop-types,它有 isomorphic-fetch 作为依赖。这将使您获取全局。您仍然需要将其导入您的测试文件。您可能还需要将其从 linter 中排除。

        将此添加到测试文件的顶部。

        import fetch from 'isomorphic-fetch'

        我不需要在测试套件中调用 fetch,但我需要使其可用。

        如果你使用这种方法,我想你会从你的 webpack 条目中删除 'whatwg-fetch',

        希望对你有帮助

        更新:可能的解决方案 #2

        使用上面的 @zvona 示例,但在您的应用中创建一个 MOCKS 文件夹。然后是一个文件 /globalMock.js。您可能没有正确设置它。

           __MOCKS__/globalMock.js
        
           // use one of these imports 
        
           import { fetch } from 'whatwg-fetch' // if you want to keep using the polyfill
        
           import { fetch } from 'isomorphic-fetch' // from a dependency node module that I spoke of in the previous solution.
        
           global.fetch = fetch
        

        现在在 package.json 中

        将此添加到您的 Jest 配置中:

        "jest": {
            "verbose": true,
            "rootDir": "app",
            "setupFiles": ["<rootDir>/__MOCKS__/globalMock.js"]
          }
        

        这将允许在您的测试中使用 fetch。

        我还必须对 localStorage 使用相同的概念。我保存 Jest 无法访问的所有全局变量的位置。

        【讨论】:

        • 一点也不晚!我照你说的那样,但仍然有问题......我也尝试将 isomorphic-fetch 作为我的 webpack 条目,但它没有改变任何东西,错误消息仍然是一样的。
        • 添加了一个更新,也刚刚在fetch github 文档上看到了这个:“如果这个 polyfill 在 Node.js 环境下不起作用,那是意料之中的,因为这个项目是为 Web 浏览器设计的仅限。您应该确保您的应用程序不会尝试在服务器上打包和运行它。”
        • 嗨,我做了这些更改,但仍然没有运气。我正在考虑从 fetch 转移到 axios 作为解决方案...感谢您的帮助。
        【解决方案4】:

        我已经在 spec 中使用了:

        import { fetch } from 'whatwg-fetch';
        
        global.fetch = fetch;
        

        它在 Jest 上的工作与预期一样。

        【讨论】:

        • 它对我不起作用。我已经在我的测试文件中的所有内容之上添加了导入。
        猜你喜欢
        • 2019-08-08
        • 2020-11-19
        • 2018-06-17
        • 1970-01-01
        • 2023-03-03
        • 2020-07-10
        • 2017-12-15
        • 2020-06-26
        • 2022-01-18
        相关资源
        最近更新 更多