我正在从使用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
,但是它没有任何模拟作用。
答案 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
的模拟定义为值而不是函数,这可能导致在实际模拟模块时测试失败。
无论如何,模拟模块有两种主要方法
想法是先模拟导入,然后定义模拟的实现。
import moment from 'moment-timezone'
import * as dateUtils from 'utils/dateUtils'
jest.mock('utils/dateUtils')
dateUtils.getToday = () => moment(new Date('2018-01-01'))
在这里,您将使用模块的模拟实现创建一个模拟文件,该模拟文件将在模拟模块的任何位置导入。该模拟文件必须位于__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