Jest: لا يُسمح لمصنع الوحدة النمطية الخاص بـ `` jest.mock () '' بالإشارة إلى أي متغيرات خارج النطاق

تم إنشاؤها على ١١ يناير ٢٠١٧  ·  33تعليقات  ·  مصدر: facebook/jest

أنا أستخدم المقتطف من # 1960 لأحاكى Picker في RN

import React, {Component} from 'react';

jest.mock(`Picker`, () => {
 // ...etc
});

يعمل بشكل جيد في Jest 17 ، ويلقي الخطأ التالي في Jest 18:

/Users/simonsmith/Sites/new-look/newlookapp/test/unit/setup.js: babel-plugin-jest-hoist: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
    Invalid variable access: React
    Whitelisted objects: Array, ArrayBuffer, ..... etc

أنا أستخدم React 15.4.2 و RN 0.40

لقد جربت babel-jest@test وهي تعمل كما هو متوقع ولكن كل اللقطات الخاصة بي تفشل ، يبدو أن المزيد من الدعائم قادمة والتي ربما لا علاقة لها بهذا.

أي شيء يمكنني القيام به لإصلاح هذا الآن أم يجب أن أنتظر الإصدار التالي مقابل babel-jest ؟

شكرا :)

التعليق الأكثر فائدة

لقد ساعدني استخدام jest.doMock بدلاً من jest.mock .

ال 33 كومينتر

ما عليك القيام به:

jest.mock(`Picker`, () => {
  const React = require('react');
});

كان هذا خطأ قمنا بإصلاحه. في محاكاة يمكنك طلب أشياء محليًا فقط ولا يُسمح لك بالوصول إلى المتغيرات الخارجية.

لشرح السبب: باستخدام jest.resetModules() يمكنك إعادة تعيين جميع الوحدات المتاحة حاليًا ، لذلك عندما تطلب ، ستحصل على إصدار جديد من كل وحدة. إذا كنت تستخدم React من المستوى الأعلى ، فسينتهي بك الأمر بامتلاك نسختين من React.

آه ها ، هذا هو الشيء الذي لم أستطع فعله. شكرا!

هذا الاستخدام لا بأس به وهناك فتحة هروب له. استدعاء المتغير الخاص بك mockFoo .

ولكن ، إذا كان لدي العديد من الوحوش:

jest.mock('./OfferList', () => 'OfferList');
jest.mock('./OfferHeader', () => 'OfferHeader');
jest.mock('./OfferHiredModal', () => 'OfferHiredModal');

هل يجب أن أضع const React = require('React'); في كل صورة وهمية؟

نعم.

jest.mock(`Picker`, () => {
  const React = require('React');
});

في حال قام أي شخص بنسخ هذا ولصقه ورأى أنه فشل في CI (دائرة / gitlab) وليس محليًا ، تأكد من أن React هو حرف صغير react

jest.mock(`Picker`, () => {
  const React = require('react');
});

cpojer أريد استخدام متغير __dirname ، غير مسموح به أيضًا ، كيف يمكنني الحصول عليه؟
لا أريد استخدام مسار بيئة معنية ، مثل /Users/xx/project

cpojer أنا لا أفهم حقًا تفسيرك:

إذا كنت تستخدم React من المستوى الأعلى ، فسينتهي بك الأمر بامتلاك نسختين من React.

إذا كنت بحاجة إلى React محليًا ، فسوف يكون لدي أيضًا نسختان من React المحلي ، أليس كذلك؟

فقط إذا اتصلت بـ jest.resetModules() بين الاثنين تتطلب مكالمات.

كيف تجعل هذا العمل مع وحدات ES6 ، والتي لا يمكن وضعها داخل نطاق الوظيفة؟

يمكنك استخدام الوظيفة import ، جنبًا إلى جنب مع على سبيل المثال https://github.com/airbnb/babel-plugin-dynamic-import-node

SimenB شكرا ... هل يمكنك إعطاء مثال؟ أنا أستخدم TypeScript الذي يدعم عمليات الاستيراد الديناميكي ولكني لست واضحًا كيف سيعمل ذلك لأنه بعد ذلك يصبح التنفيذ الوهمي غير متزامن ، فهل يعرف Jest كيفية انتظار حل النموذج قبل متابعة حالات الاختبار؟

فقط انتظر الوعد.

let myDep;

beforeEach(async () => {
  jest.resetModules();

  myDep = await import('./some-modules.js');
})

لا توجد فكرة عن كيفية ظهور ذلك مع الكتابة المطبوعة ، ولكن لا ينبغي أن تكون مختلفة جدًا

أواجه مشكلة في الاستهزاء بوظيفة تستخدم بناء جملة ES6 داخل مثال:

/**
 * @jest-environment jsdom
 */

import SagaTester from "redux-saga-tester";
import supportRequests from "sagas/support_requests";
import reducers from "reducers";

import { fetched } from "actions/support_requests";

describe("success", () => {
  it("sends the message via connection", async () => {
    const sagaTester = new SagaTester({
      reducers: reducers,
      initialState: {
        router: { location: { pathname: "/support_requests" } },
        supportRequests: null,
        authenticated: true,
        currentUser: { isSupportAgent: true },
      },
    });
    jest.mock("sagas/oauth", () => {
      return {
        ...require.requireActual("sagas/oauth"),
        callFetch: function* () {
          return { ok: true, json: () => Promise.resolve({ support_requests: [], meta: { pagination: {} } }) };
        },
      };
    });
    sagaTester.start(supportRequests);
    await sagaTester.waitFor(fetched);
  });
});

يتم تحويل عامل الانتشار (...) ووظيفة المولد بواسطة babel إلى شيء يستخدم _extends و regeneratorRuntime وفقًا لذلك لا يمكن الوصول إليه:

babel-plugin-jest-hoist: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
    Invalid variable access: _extends
    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, console, 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.
    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.

هل عانى أي شخص من هذه المشكلة من قبل؟ أنا استخدم أحدث مزحة.

الحصول على نفس الخطأ ولكن مع:

Invalid variable access: _asyncToGenerator

أنا أستخدم برنامج babel-plugin-transform-regenerator. كيف يمكنني الدعابة لعدم الشكوى من "عدم السماح" لمصنع الوحدة jest.mock() "بالإشارة إلى أي متغيرات خارج النطاق" في هذه الحالة ؟!

// تعديل:
الاختبار الكامل

it('should request data via API', async () => {
    const store = mockStore({ fields: initialState });
    jest.resetModules();
    jest.mock('services/api-client', () => ({
        getFieldsByFarm: async () => {
            return [{ field: {} }];
        },
    }));
    const Actions = require('./actions');
    const expected = [
        { type: 'FIELDS/REQUEST' },
        { type: 'FIELDS/RECEIVE', payload: { items: [{ field: {} }], didInvalidate: false },},
    ];
    await store.dispatch(Actions.getFieldsByFarm());
    const dispatchedActions = store.getActions();
    expect(dispatchedActions[0]).toEqual(expected[0]);
    expect(dispatchedActions[1].payload).toEqual(expect.objectContaining(expected[1].payload));
});

إن التفاف بعض أجزاء الاختبار في IIFE غير متزامن وإزالة async أمام وظيفة الاختبار يجعل المزاح لا يخطئ:

 it('should request data via API', (done) => {
    const store = mockStore({ fields: initialState });
    jest.resetModules();
    jest.mock('services/api-clients/nana', () => ({
        getFieldsByFarm: async () => {
            return [{ field: {} }];
        },
    }));
    const Actions = require('./actions');
    (async () => {
        const expected = [
            { type: 'FIELDS/REQUEST' },
            {
                type: 'FIELDS/RECEIVE',
                payload: { items: [{ field: {} }], didInvalidate: false },
            },
        ];
        await store.dispatch(Actions.getFieldsByFarm());
        const dispatchedActions = store.getActions();
        expect(dispatchedActions[0]).toEqual(expected[0]);
        expect(dispatchedActions[1].payload).toEqual(expect.objectContaining(expected[1].payload));
        done();
    })();
});

لقد ساعدني استخدام jest.doMock بدلاً من jest.mock .

لست متأكدًا تمامًا حتى الآن نظرًا لوجود أشياء أخرى تفشل الآن (😄) ولكن يبدو أنها تساعد حقًا ، نعم. شكرا! 🙂

هل لديك أي فكرة عن سبب عدم نجاح doMock و mock ؟ الشيء الغريب بالنسبة لي هو أيضًا أنني إذا وضعت المتغير باسم "MockedComponent" ، فقد تلقيت خطأ ، ولكن عندما وضعت "mockedComponent" لم يكن هناك خطأ ، لكن الإشارة كانت "غير محددة".

يتم نقل مكالمات 'jest.mock' من استدعاءات 'it' إلى الإغلاق الخارجي بواسطة معالج مسبق ولا يعمل بشكل جيد. لا تتأثر مكالمات 'jest.doMock' بالمعالج المسبق.

أواجه هذه المشكلة عندما أقوم بتشغيل الدعابة باستخدام nodejs 10.0.0 ، فقط إصدار العقدة الذي تم إرجاعه إلى إصدار أقدم هو العمل.

Soontao لا أستطيع إعادة إنتاج ذلك ، هل أنت قادر على إعداد استنساخ صغير؟

تضمين التغريدة
شكرًا لردك السريع ، ولكن عندما أحاول إعادة إنتاج ذلك باستخدام node v10 ، وجدت أن جميع الاختبارات تعمل بشكل جيد ، أعتقد أن المشكلة ربما تكون ناتجة عن أسباب أخرى ، وقد فقدتها عندما أعد تثبيت nodejs.

نفس المشكلة عند التشغيل مع nodejs 10.0.0

 /xxx/node_modules/react-native/jest/setup.js: babel-plugin-jest-hoist: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
    Invalid variable access: console
    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.
    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:14: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)

هذا ليس له علاقة بالعقدة 10 ، كل ما في الأمر أنه ليس لدينا console في القائمة البيضاء. مرحبا بكم في العلاقات العامة! يجب علينا حقًا استخدام بعض الوحدات النمطية globals بدلاً من القائمة البيضاء اليدوية ...

آخر واحد تم إصلاحه هنا: # 6075

أدت ترقية babel-jest بـ yarn add --dev babel-jest babel-core regenerator-runtime إصلاح هذا الخطأ بالنسبة لي.

لقد عثرت للتو على هذا أثناء البحث في Google ويبدو أنني قد فاتني هذا السطر الحاسم في رسالة الخطأ مع أي شخص آخر:

_ إذا تم التأكد من أن النموذج الوهمي مطلوب بشكل كسول ، فيُسمح باستخدام الأسماء المتغيرة التي تبدأ بـ mock ._

ما عليك سوى تغيير اسم ما تسخر منه لتهزأ بـ YourComponentName

واجهت هذه المشكلة بعد أن أضفت هذا الرمز في jest.conf الخاص بي ، لإضافة دعم tsx في الاختبارات (بدون هذا الرمز ، لا يمكنني كتابة tsx في ملفات spec.tsx الخاصة بي:

  globals: {
    jasmine: true,
+   'ts-jest': {
+     babelConfig: true
+   }
  }
module.exports = {
  // eslint-disable-next-line no-undef
  rootDir: path.resolve(__dirname, '../'),
  roots: ['<rootDir>/src'],
  verbose: false,
  moduleFileExtensions: ['ts', 'tsx', 'vue', 'js', 'jsx', 'json'],
  testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.(ts|js)x?$',
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1'
  },
  transform: {
    '^.+\\.vue$': 'vue-jest',
    '^.+\\.(js|jsx)?$': 'babel-jest',
    '^.+\\.tsx?$': 'ts-jest'
  },
  transformIgnorePatterns: ['<rootDir>/node_modules/(?!lodash-es)'],
  snapshotSerializers: ['<rootDir>/node_modules/jest-serializer-vue'],
  setupFilesAfterEnv: ['<rootDir>/test/jest.init.ts'],

  // run tests with --coverage to see coverage
  coverageDirectory: '<rootDir>/test/coverage',
  coverageReporters: ['html', 'text-summary'],
  collectCoverageFrom: ['src/**/*.{ts,tsx,js,jsx,vue}', '!**/node_modules/**'],

  globals: {
    jasmine: true,
    'ts-jest': {
      babelConfig: true
    }
  }
}

حصلت على خطأ:

   babel-plugin-jest-hoist: The module factory of `jest.mock()` is not allowed to reference any out-of-scope variables.
    Invalid variable access: _debounce
    Whitelisted objects: Array, ArrayBuffer, Boolean, DataView, Date, Error, EvalError, Float32Array, Float64Array, Function, Generator, GeneratorFunction, Infinity, Int16Arra
y, Int32Array, Int8Array, InternalError, Intl, JSON, Map, Math, NaN, Number, Object, Promise, Proxy, RangeError, ReferenceError, Reflect, RegExp, Set, String, Symbol, SyntaxEr
ror, TypeError, URIError, Uint16Array, Uint32Array, Uint8Array, Uint8ClampedArray, WeakMap, WeakSet, arguments, console, expect, isNaN, jest, parseFloat, parseInt, require, un
defined, DTRACE_NET_SERVER_CONNECTION, DTRACE_NET_STREAM_END, DTRACE_HTTP_SERVER_REQUEST, DTRACE_HTTP_SERVER_RESPONSE, DTRACE_HTTP_CLIENT_REQUEST, DTRACE_HTTP_CLIENT_RESPONSE,
 COUNTER_NET_SERVER_CONNECTION, COUNTER_NET_SERVER_CONNECTION_CLOSE, COUNTER_HTTP_SERVER_REQUEST, COUNTER_HTTP_SERVER_RESPONSE, COUNTER_HTTP_CLIENT_REQUEST, COUNTER_HTTP_CLIEN
T_RESPONSE, global, process, Buffer, clearImmediate, clearInterval, clearTimeout, setImmediate, setInterval, setTimeout.
    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` (case inse
nsitive) are permitted.

الكود نفسه:

const DEBOUNCE_DELAY = 10
const _debounce = jest.requireActual('lodash-es/debounce').default
jest.mock('lodash-es/debounce', () =>
  jest.fn((fn) => _debounce(fn, DEBOUNCE_DELAY))
)

اضطررت إلى إعادة كتابته برقم سحري واستيراد مضمّن:

jest.mock('lodash-es/debounce', () =>
  jest.fn((fn) => jest.requireActual('lodash-es/debounce').default(fn, 10))
)

لاحظ أنه بدون هذا التكوين في الكود globals ( 'ts-jest': { babelConfig: true } ) يعمل بشكل جيد. لكن بدون هذا السطر في التكوين ، لم أتمكن من إجراء الاختبارات باستخدام tsx ، واجهت هذا الخطأ:

    Jest encountered an unexpected token

    This usually means that you are trying to import a file which Jest cannot parse, e.g. it's not plain JavaScript.

    By default, if Jest sees a Babel config, it will use that to transform your files, ignoring "node_modules".

    Here's what you can do:
     • To have some of your "node_modules" files transformed, you can specify a custom "transformIgnorePatterns" in your config.
     • If you need a custom transformation specify a "transform" option in your config.
     • If you simply want to mock your non-JS modules (e.g. binary assets) you can stub them out with the "moduleNameMapper" config option.

    You'll find more details and examples of these config options in the docs:
    https://jestjs.io/docs/en/configuration.html

    Details:

    C:\Users\Alend\vue-project\src\my-component\MyComponent.spec.tsx:20
                            render: function () { return <div id="foo">Foo</div>; }
                                                         ^

بعض إصدارات package.json:

"@babel/core": "^7.4.5",
"babel-core": "^7.0.0-bridge.0",
"babel-jest": "24.8.0",
"jest": "24.8.0",
"ts-jest": "24.0.2",

و babel config نفسها:

module.exports = {
  presets: [
    [
      '@babel/preset-env',
      {
        modules: 'commonjs',
        targets: {
          browsers: ['> 1%', 'last 2 versions', 'not ie <= 11']
        }
      }
    ],
    '@vue/babel-preset-jsx'
  ],
  plugins: [
    '@babel/plugin-proposal-class-properties',
    '@babel/plugin-proposal-export-namespace-from',
    '@babel/plugin-proposal-function-sent',
    '@babel/plugin-proposal-json-strings',
    '@babel/plugin-proposal-numeric-separator',
    '@babel/plugin-proposal-throw-expressions',
    '@babel/plugin-syntax-dynamic-import',

    ['@babel/plugin-transform-runtime', { corejs: 2 }],
    ['@babel/plugin-proposal-decorators', { legacy: true }]
  ]
}

يبدو أن هذه المشكلة لا تزال موجودة وحتى الآن لا تساعد الحلول البديلة في إنشاء تطبيق تطبيق تفاعلي

"
ReferenceError: لم يتم تعريف mockComponent

  17 | const mockComponent = () => <div>Mock</div>;
  18 | 
> 19 | jest.mock('./components/Component', () => ({ Component: mockComponent }));

"

تضمين التغريدة
سيرفع Jest تلقائيًا مكالمات jest.mock إلى الجزء العلوي من الوحدة.
هذا هو السبب في أن mockComponent const لم يتم تعريفها بعد عند تشغيل jest.mock.

للتغلب على هذه "المشكلة / الميزة" ، أفعل ذلك في خطوتين على النحو التالي:

jest.mock('./components/Component', () => ({ Component: jest.fn() }));
import { Component } from "./components/Component";

Component.mockImplementation(() => <div>Mock</div>);

تضمين التغريدة
سيرفع Jest تلقائيًا مكالمات jest.mock إلى الجزء العلوي من الوحدة.
هذا هو السبب في أن mockComponent const لم يتم تعريفها بعد عند تشغيل jest.mock.

للتغلب على هذه "المشكلة / الميزة" ، أفعل ذلك في خطوتين على النحو التالي:

jest.mock('./components/Component', () => ({ Component: jest.fn() }));
import { Component } from "./components/Component";

Component.mockImplementation(() => <div>Mock</div>);

هل هذا حقا صحيح؟ كما ذكر nckblu أعلاه ، يجب أن تكون المتغيرات التي تبدأ بـ "mock" متاحة كاستثناء. و "mockComponent" يجب أن يقع في هذا الاستثناء ، أليس كذلك؟

في هذه الأثناء ، إذا كنت تريد حلًا بديلًا لإضافة بيان تصحيح الأخطاء ، مثل console.log ('Checking ...') ، فابدأ console.log مع global لجعلها تعمل.

global.console.log('global console working')

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات