मैं जेस्ट का उपयोग करके एक ईएस 6 मॉड्यूल आयात कैसे कर सकता हूं?


281

मुझे लगता है कि यह संभव नहीं है, लेकिन मैं वैसे भी पूछना चाहता हूं।

मैं यह परीक्षण करना चाहता हूं कि मेरा एक ईएस 6 मॉड्यूल एक विशेष तरीके से दूसरे ईएस 6 मॉड्यूल को कॉल करता है। जैस्मीन के साथ यह सुपर आसान है -

एप्लिकेशन कोड:

// myModule.js
import dependency from './dependency';

export default (x) => {
  dependency.doSomething(x * 2);
}

और परीक्षण कोड:

//myModule-test.js
import myModule from '../myModule';
import dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    spyOn(dependency, 'doSomething');

    myModule(2);

    expect(dependency.doSomething).toHaveBeenCalledWith(4);
  });
});

Jest के समतुल्य क्या है? मुझे ऐसा लगता है कि ऐसा करना आसान है, लेकिन मैं अपने बालों को बाहर निकालने की कोशिश कर रहा हूं।

मैं जो निकटतम आया हूं , वह importएस को requireएस के स्थान पर बदल रहा है , और उन्हें परीक्षणों / कार्यों के अंदर ले जा रहा है। न तो ऐसी चीजें हैं जो मैं करना चाहता हूं।

// myModule.js
export default (x) => {
  const dependency = require('./dependency'); // yuck
  dependency.doSomething(x * 2);
}

//myModule-test.js
describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    jest.mock('../dependency');

    myModule(2);

    const dependency = require('../dependency'); // also yuck
    expect(dependency.doSomething).toBeCalledWith(4);
  });
});

बोनस पॉइंट्स के लिए, मैं पूरी बात काम करना पसंद करूँगा जब फंक्शन अंदर dependency.jsडिफॉल्ट एक्सपोर्ट हो। हालाँकि, मुझे पता है कि डिफ़ॉल्ट निर्यात पर जासूसी काम नहीं करती है (या कम से कम मैं इसे काम करने के लिए कभी नहीं प्राप्त कर सकता), इसलिए मैं उम्मीद नहीं कर रहा हूं कि यह जेस्ट में भी संभव है।


मैं वैसे भी इस परियोजना के लिए बैबल का उपयोग कर रहा हूं, इसलिए मुझे अब importएस के लिए requireएस ट्रांसपाइल एस के लिए जारी रखने में कोई आपत्ति नहीं है । फिर भी आगाह करने के लिए धन्यवाद।
कैम जैक्सन

क्या होगा अगर मेरे पास ts ए कक्षा है और यह कुछ फ़ंक्शन को कक्षा बी के doSomething () कहता है कि हम कैसे मॉक कर सकते हैं ताकि क्लास ए क्लास बी फ़ंक्शन doSomething () के नकली संस्करण को कॉल करता है
कैलाश योगेश्वर

उन लोगों के लिए जो इस मुद्दे को अधिक जानना चाहते हैं github.com/facebook/jest/issues/936
omeralper

जवाबों:


219

मैं एक हैक का उपयोग करके इसे हल करने में सक्षम है import *। यह भी नाम और डिफ़ॉल्ट दोनों निर्यात के लिए काम करता है!

एक नामित निर्यात के लिए:

// dependency.js
export const doSomething = (y) => console.log(y)

// myModule.js
import { doSomething } from './dependency';

export default (x) => {
  doSomething(x * 2);
}

// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    dependency.doSomething = jest.fn(); // Mutate the named export

    myModule(2);

    expect(dependency.doSomething).toBeCalledWith(4);
  });
});

या डिफ़ॉल्ट निर्यात के लिए:

// dependency.js
export default (y) => console.log(y)

// myModule.js
import dependency from './dependency'; // Note lack of curlies

export default (x) => {
  dependency(x * 2);
}

// myModule-test.js
import myModule from '../myModule';
import * as dependency from '../dependency';

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    dependency.default = jest.fn(); // Mutate the default export

    myModule(2);

    expect(dependency.default).toBeCalledWith(4); // Assert against the default
  });
});

जैसा कि मिहाई डेमियन ने बहुत ही सही ढंग से नीचे बताया है, यह मॉड्यूल ऑब्जेक्ट को म्यूट कर रहा है dependency, और इसलिए यह अन्य परीक्षणों में 'लीक' होगा। इसलिए यदि आप इस दृष्टिकोण का उपयोग करते हैं तो आपको मूल मूल्य संग्रहीत करना चाहिए और फिर प्रत्येक परीक्षण के बाद इसे फिर से सेट करना चाहिए। जेस्ट के साथ आसानी से ऐसा करने के लिए, इसके बजाय जासूसी () विधि का उपयोग करें jest.fn()क्योंकि यह आसानी से अपने मूल मूल्य को बहाल करने का समर्थन करता है, इसलिए उल्लेखित 'लीक' से पहले परहेज करें।


साझा करने के लिए धन्यवाद। मुझे लगता है कि शुद्ध परिणाम इस के समान है - लेकिन यह क्लीनर हो सकता है - stackoverflow.com/a/38414160/1882064
arcseldon

64
यह काम करता है, लेकिन यह शायद एक अच्छा अभ्यास नहीं है। परीक्षण के दायरे के बाहर की वस्तुओं के परिवर्तन परीक्षणों के बीच बने रहते हैं। यह बाद में अन्य परीक्षणों में अप्रत्याशित परिणाम पैदा कर सकता है।
मिहाई

10
Jest.fn () का उपयोग करने के बजाय, आप jest.spyOn () का उपयोग कर सकते हैं ताकि आप बाद में मूल विधि को पुनर्स्थापित कर सकें, इसलिए यह अन्य परीक्षणों में नहीं बहता है। मुझे यहां विभिन्न दृष्टिकोणों (jest.fn, jest.mock और jest.spyOn) के बारे में अच्छा लेख मिला: medium.com/@rickhanlonii/understanding-jest-mocks-f0046c68e53c
Martinsos

2
बस एक नोट: यदि dependencyउसी फ़ाइल पर निवास किया जाता है myModule, तो यह काम नहीं करेगा।
लू ट्रान

2
मुझे लगता है कि यह टाइपस्क्रिप्ट के साथ काम नहीं करेगा जिस वस्तु को आप बदल रहे हैं वह केवल पढ़ने के लिए है।
adredx

171

आपको मॉड्यूल का मज़ाक उड़ाना होगा और अपने आप से जासूस सेट करना होगा:

import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency', () => ({
  doSomething: jest.fn()
}))

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    myModule(2);
    expect(dependency.doSomething).toBeCalledWith(4);
  });
});

4
यह सही नहीं लगता। मुझे मिलता है: babel-plugin-jest-hoist: The second argument of jest.mock must be a function.तो कोड भी संकलन नहीं है।
कैम जैक्सन

3
क्षमा करें, मैंने अपना कोड अपडेट कर दिया है। कृपया यह भी ध्यान दें कि jest.mockपरीक्षण फ़ाइल के सापेक्ष पथ है ।
एंड्रियास कोबर्ले

1
इसने मेरे लिए काम किया, हालांकि, डिफ़ॉल्ट निर्यात का उपयोग करते समय नहीं।
आइरिस शेफ़र

4
@IrisSchaffer डिफ़ॉल्ट निर्यात के साथ यह काम __esModule: trueकरने के लिए आपको नकली वस्तु में जोड़ना होगा। यह ट्रांसप्लड कोड द्वारा उपयोग किया जाने वाला आंतरिक ध्वज है, यह निर्धारित करने के लिए कि यह ट्रांसप्लड es6 मॉड्यूल है या एक आमjs मॉड्यूल है।
जोहान्स लुम्पे

24
डिफ़ॉल्ट निर्यात निर्यात: jest.mock('../dependency', () => ({ default: jest.fn() }))
Neob91

50

कीट का उपयोग कर ES6 निर्भरता मॉड्यूल डिफ़ॉल्ट निर्यात का मजाक उड़ाना:

import myModule from '../myModule';
import dependency from '../dependency';

jest.mock('../dependency');

// If necessary, you can place a mock implementation like this:
dependency.mockImplementation(() => 42);

describe('myModule', () => {
  it('calls the dependency once with double the input', () => {
    myModule(2);

    expect(dependency).toHaveBeenCalledTimes(1);
    expect(dependency).toHaveBeenCalledWith(4);
  });
});

अन्य विकल्पों ने मेरे मामले के लिए काम नहीं किया।


6
अगर मैं सिर्फ एक टेस्ट के लिए बनाना चाहता हूं तो इसे साफ करने का सबसे अच्छा तरीका क्या है? बाद में? `` `` के बाद (() => {jest.unmock (../ निर्भरता ');}) `` ``
nxmohamad

1
@falsarella doMock वास्तव में उस मामले में काम करता है? मैं बहुत समान मुद्दा रहा हूँ और जब मैं विशिष्ट परीक्षण के अंदर jest.doMock की कोशिश कर रहा हूँ तो यह कुछ भी नहीं करता है, जहाँ पूरे मॉड्यूल के लिए jest.mock सही तरीके से काम कर रहा है
प्रगति

1
@ प्रगति 1ve आप mockImplementationOnce के साथ jest.mock का उपयोग करने की कोशिश कर सकते हैं
falsarella

1
हाँ, यह एक मान्य सुझाव है, हालाँकि इसके लिए परीक्षण की आवश्यकता है और मैं इस तरह से परीक्षण लिखने का प्रशंसक नहीं हूँ। मुझे बाहरी मॉड्यूल आयात करने और विशिष्ट कार्यों पर स्पाईऑन का उपयोग करके उन मुद्दों के आसपास मिला।
प्रगति 1

1
@ Progress1ve हम्म का मतलब था कि मैं प्रत्येक विशिष्ट परीक्षण के अंदर mockImplementationOnce को जगह दूं ... वैसे भी, मुझे खुशी है कि आपने एक समाधान ढूंढ लिया है :)
falsarella

38

एंड्रियास उत्तर के लिए और अधिक जोड़ना। मुझे ES6 कोड के साथ भी यही समस्या थी लेकिन आयात को म्यूट नहीं करना चाहता था। वह हैकी लग रही थी। इसलिए मैंने ऐसा किया

import myModule from '../myModule';
import dependency from '../dependency';
jest.mock('../dependency');

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    myModule(2);
  });
});

और dependency.js के समानांतर "__ mocks __" फ़ोल्डर में निर्भरता। js जोड़ा । इसने मेरे लिए काम किया। इसके अलावा, इसने मुझे मॉक कार्यान्वयन से उपयुक्त डेटा वापस करने का विकल्प दिया। सुनिश्चित करें कि आप उस मॉड्यूल का सही मार्ग दें जिसे आप मॉक करना चाहते हैं।


इसके लिए धन्यवाद। इसकी एक बार कोशिश करूंगा। इस समाधान को भी पसंद किया - stackoverflow.com/a/38414160/1882064
arcseldon

इस दृष्टिकोण के बारे में मुझे जो पसंद है वह यह है कि यह आपको उन सभी अवसरों के लिए एक मैनुअल मॉक प्रदान करने की संभावना देता है जिसमें आप एक विशिष्ट मॉड्यूल का मजाक बनाना चाहते हैं। उदाहरण के लिए, मेरे पास अनुवाद सहायक है, जिसका उपयोग कई स्थानों पर किया जाता है। __mocks__/translations.jsफ़ाइल बस निर्यात डिफ़ॉल्ट jest.fn()की तरह कुछ में:export default jest.fn((id) => id)
आइरिस Schaffer

तुम भी jest.genMockFromModuleमॉड्यूल से नकली उत्पन्न करने के लिए उपयोग कर सकते हैं । facebook.github.io/jest/docs/…
वरुणकुमार नागराजन

2
ध्यान देने वाली बात यह है कि ES6 मॉड्यूल्स को 'jest.mock (' .. डिपेंडेंसी ') कहने के बाद export default jest.genMockFromModule('../dependency')सौंपे गए सभी dependency.defaultफंक्शन्स होंगे, लेकिन अन्यथा अपेक्षित व्यवहार करें।
jhk

7
आपका परीक्षण क्या दिखता है? जो उत्तर के एक महत्वपूर्ण भाग की तरह लगता है। expect(???)
पत्थर

14

2020 तक तेजी से आगे बढ़ते हुए, मैंने इस लिंक को समाधान पाया। केवल ES6 मॉड्यूल सिंटैक्स का उपयोग कर https://remarkablemark.org/blog/2018/06/28/jest-mock-default-onym-export/

// esModule.js
export default 'defaultExport';
export const namedExport = () => {};

// esModule.test.js
jest.mock('./esModule', () => ({
  __esModule: true, // this property makes it work
  default: 'mockedDefaultExport',
  namedExport: jest.fn(),
}));

import defaultExport, { namedExport } from './esModule';
defaultExport; // 'mockedDefaultExport'
namedExport; // mock function

इसके अलावा एक बात जो आपको पता होनी चाहिए (जो मुझे पता करने में थोड़ी देर लगी) वह यह है कि आप परीक्षण के अंदर jest.mock () को कॉल नहीं कर सकते हैं; आपको इसे मॉड्यूल के शीर्ष स्तर पर कॉल करना होगा। हालाँकि, आप अलग-अलग परीक्षणों के अंदर mockI कार्यान्वयन () को कॉल कर सकते हैं यदि आप अलग-अलग परीक्षणों के लिए अलग-अलग नकली सेट करना चाहते हैं।


5

प्रश्न पहले से ही उत्तर दिया गया है लेकिन आप इसे इस तरह हल कर सकते हैं:

dependency.js

const doSomething = (x) => x
export default doSomething;

myModule.js:

import doSomething from "./dependency";

export default (x) => doSomething(x * 2);

myModule.spec.js:

jest.mock('../dependency');
import doSomething from "../dependency";
import myModule from "../myModule";

describe('myModule', () => {
  it('calls the dependency with double the input', () => {
    doSomething.mockImplementation((x) => x * 10)

    myModule(2);

    expect(doSomething).toHaveBeenCalledWith(4);
    console.log(myModule(2)) // 40
  });
});

लेकिन "आवश्यकता" कॉमनजेएस सिंटेक्स है - ओपी ईएस 6 मॉड्यूल के बारे में पूछ रहा था
एंडी

@ आपकी टिप्पणी के लिए धन्यवाद, मैंने अपना उत्तर अपडेट कर दिया। तर्क में एक ही बात BTW।
स्लिम

2

मैंने इसका दूसरा तरीका हल किया। मान लीजिए कि आपके पास आपकी निर्भरता है

export const myFunction = () => { }

मैं निम्नलिखित सामग्री के साथ इसके अलावा एक depdency.mock.js फ़ाइल बनाता हूं:

export const mockFunction = jest.fn();

jest.mock('dependency.js', () => ({ myFunction: mockFunction }));

और परीक्षण में, इससे पहले कि मैं जिस फाइल का उपयोग करता हूं, उसका आयात करूँ:

import { mockFunction } from 'dependency.mock'
import functionThatCallsDep from './tested-code'

it('my test', () => {
    mockFunction.returnValue(false);

    functionThatCallsDep();

    expect(mockFunction).toHaveBeenCalled();

})
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.