在玩笑功能中使用导入的变量

时间:2018-07-04 07:15:57

标签: reactjs jestjs

我正在从使用moment的文件中模拟一个函数,这是文件内容:

./ utils / dateUtils:

import moment from 'moment-timezone'

export function getToday() {
  return moment().tz(commonTimeZone)
}


./containers/someContainer.js:

import { getToday } from 'utils/dateUtils'

// Uses getToday in the component


./containers/someContainer.spec.js:

import moment from 'moment-timezone'

jest.mock('utils/dateUtils', () => {
  return {
    getToday : moment(new Date('2018-01-01'))
  }
})

测试抛出此错误:

● Test suite failed to run

    /Users/bharat/Documents/redmart-repo/partner-portalv2/app/containers/Orders/PickupsContainer.test.js: babel-plugin-jest-hoist: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
    Invalid variable access: moment
    Whitelisted objects: Array, ArrayBuffer, Boolean, DataView, Date, Error, EvalError, Float32Array, Float64Array, Function, Generator, GeneratorFunction, Infinity, Int16Array, Int32Array, Int8Array, InternalError, Intl, JSON, Map, Math, NaN, Number, Object, Promise, Proxy, RangeError, ReferenceError, Reflect, RegExp, Set, String, Symbol, SyntaxError, TypeError, URIError, Uint16Array, Uint32Array, Uint8Array, Uint8ClampedArray, WeakMap, WeakSet, arguments, expect, jest, require, undefined, DTRACE_NET_SERVER_CONNECTION, DTRACE_NET_STREAM_END, DTRACE_HTTP_SERVER_REQUEST, DTRACE_HTTP_SERVER_RESPONSE, DTRACE_HTTP_CLIENT_REQUEST, DTRACE_HTTP_CLIENT_RESPONSE, global, process, Buffer, clearImmediate, clearInterval, clearTimeout, setImmediate, setInterval, setTimeout, console.
    Note: This is a precaution to guard against uninitialized mock variables. If it is ensured that the mock is required lazily, variable names prefixed with `mock` are permitted.

      at invariant (node_modules/babel-plugin-jest-hoist/build/index.js:12:11)
      at newFn (node_modules/babel-traverse/lib/visitors.js:276:21)
      at NodePath._call (node_modules/babel-traverse/lib/path/context.js:76:18)
      at NodePath.call (node_modules/babel-traverse/lib/path/context.js:48:17)
      at NodePath.visit (node_modules/babel-traverse/lib/path/context.js:105:12)
      at TraversalContext.visitQueue (node_modules/babel-traverse/lib/context.js:150:16)
      at TraversalContext.visitMultiple (node_modules/babel-traverse/lib/context.js:103:17)

不确定此处缺少什么,有人知道如何解决此错误。

P.S。我尝试过jest.doMock,但是它没有任何模拟作用。

2 个答案:

答案 0 :(得分:2)

您需要以模拟方式在本地要求这些软件包,以确保不使用任何外部变量-

jest.mock('utils/dateUtils', () => {
  const moment = require("moment-timezone");
  return {
    getToday : moment(new Date('2018-01-01'))
  }
})

以下是相关问题的链接-https://github.com/facebook/jest/issues/2567

答案 1 :(得分:1)

您的问题是jest.mock调用被挂起了 ,这意味着它们被放在文件的最顶部。在文档中找到它有点棘手,但他们在jest.doMock下说。

这使您执行的代码看起来像这样:

jest.mock('utils/dateUtils', () => {
  return {
    getToday : moment(new Date('2018-01-01'))
  }
})

import moment from 'moment-timezone'

并且您可以看到moment在导入之前已使用,因此出现了有关引用范围外变量的错误消息。

有多种方法可以避免这种情况。

但是,使用jest.doMock应该避免吊装。我想知道路径是否缺少类似'../utils...的内容–请注意开头的../

还有一个事实是,您将getToday的模拟定义为值而不是函数,这可能导致在实际模拟模块时测试失败。

无论如何,模拟模块有两种主要方法

ES6 Class Mock

想法是先模拟导入,然后定义模拟的实现。

import moment from 'moment-timezone'
import * as dateUtils from 'utils/dateUtils'

jest.mock('utils/dateUtils')

dateUtils.getToday = () => moment(new Date('2018-01-01'))

Manual Mock

在这里,您将使用模块的模拟实现创建一个模拟文件,该模拟文件将在模拟模块的任何位置导入。该模拟文件必须位于__mocks__文件夹中,该文件夹必须与您要模拟的文件处于同一级别。例如:

├── utils
│   ├── __mocks__
│   │   └── dateUtils.js
│   └── dateUtils.js
│
├── other folders

代码如下:

// utils/__mocks__/dateUtils.js
import moment from 'moment-timezone'

export const getToday = () => moment(new Date('2018-01-01'))

测试:

// containers/someContainer.spec.js
import * from './path/to/utils/dateUtils'

jest.mock('./path/to/utils/dateUtils')

// your tests here