कभी-कभी आप कुछ परीक्षणों में किसी फ़ंक्शन का नकल करना चाहते हैं, लेकिन अन्य में नहीं। कभी-कभी आप अलग-अलग परीक्षाओं के लिए अलग-अलग मॉक की आपूर्ति करना चाहते हैं। जेस्ट इसे पेचीदा बना देता है: इसका डिफ़ॉल्ट व्यवहार संपूर्ण परीक्षण फ़ाइल के लिए पैकेज के फ़ंक्शन को ओवरराइड करना है, न कि केवल एक परीक्षण के लिए। यदि आपने Python के @patch या Laravel के सर्विस कंटेनर जैसे लचीले टूल का उपयोग किया है तो यह अजीब लगता है।
यह पोस्ट आपको दिखाएगी कि व्यक्तिगत परीक्षणों के लिए फ़ंक्शंस का मॉक कैसे बनाया जाए, फिर यदि कोई मॉक प्रदान नहीं किया गया था तो मूल कार्यान्वयन पर वापस जाएँ। कॉमनजेएस और ईएस मॉड्यूल दोनों के लिए उदाहरण दिए जाएंगे। इस पोस्ट में प्रदर्शित तकनीकें प्रथम-पक्ष मॉड्यूल और तृतीय-पक्ष पैकेज दोनों के लिए काम करेंगी।
चूंकि हम इस पोस्ट में कई मॉड्यूल सिस्टम को कवर करेंगे, इसलिए यह समझना महत्वपूर्ण है कि वे क्या हैं।
CommonJS (संक्षिप्त रूप में CJS) Node.js में मॉड्यूल सिस्टम है। यह मॉड्यूल का उपयोग करके फ़ंक्शंस निर्यात करता है। require():
का उपयोग करके फ़ंक्शन आयात करता है।
// CommonJS export function greet() { return "Hello, world!"; } module.exports = { greet };
// CommonJS import const getUsersList = require('./greet');
ES मॉड्यूल (संक्षिप्त रूप में ESM) मॉड्यूल सिस्टम है जिसका उपयोग ब्राउज़र द्वारा किया जाता है। यह निर्यात कीवर्ड का उपयोग करके फ़ंक्शन निर्यात करता है और आयात कीवर्ड का उपयोग करके फ़ंक्शन आयात करता है:
// ES module export export default function greet() { return "Hello, world!"; }
// ES module import import { greet } from "./greet";
इस पोस्ट को लिखने के समय अधिकांश फ्रंटएंड जावास्क्रिप्ट डेवलपर ईएस मॉड्यूल का उपयोग करते हैं, और कई सर्वर-साइड जेएस देव भी उनका उपयोग करते हैं। हालाँकि, CommonJS अभी भी नोड के लिए डिफ़ॉल्ट है। चाहे आप किसी भी सिस्टम का उपयोग करें, जेस्ट के मॉकिंग सिस्टम के बारे में जानने के लिए पूरा लेख पढ़ना उचित है।
आमतौर पर एक कॉमनजेएस फ़ाइल ऑब्जेक्ट सिंटैक्स का उपयोग करके अपने मॉड्यूल निर्यात करेगी, जैसा कि नीचे दिखाया गया है:
// CommonJS export function greet() { return "Hello, world!"; } module.exports = { greet: greet };
हालाँकि, किसी फ़ंक्शन को स्वयं निर्यात करना भी संभव है:
// CommonJS export function greet() { return "Hello, world!"; } module.exports = greet;
मैं आवश्यक रूप से इसे आपके अपने कोड में करने की अनुशंसा नहीं करूंगा: किसी ऑब्जेक्ट को निर्यात करने से आपको अपना एप्लिकेशन विकसित करते समय कम सिरदर्द मिलेगा। हालाँकि, यह इतना सामान्य है कि कॉमनजेएस में एक नंगे निर्यातित फ़ंक्शन का नकल कैसे किया जाए, इस पर चर्चा करना उचित है, यदि कोई परीक्षण अपना स्वयं का कार्यान्वयन प्रदान नहीं करता है, तो मूल पर वापस लौटें।
मान लें कि हमारे पास निम्नलिखित कॉमनजेएस फ़ाइल है जिसे हम परीक्षणों के दौरान मॉक करना चाहेंगे:
// cjsFunction.js function testFunc() { return "original"; } module.exports = testFunc;
हम निम्नलिखित कोड का उपयोग करके अपने परीक्षणों में इसका अनुकरण कर सकते हैं:
const testFunc = require("./cjsFunction"); jest.mock("./cjsFunction"); beforeEach(() => { testFunc.mockImplementation(jest.requireActual("./cjsFunction")); }); it("can override the implementation for a single test", () => { testFunc.mockImplementation(() => "mock implementation"); expect(testFunc()).toBe("mock implementation"); expect(testFunc.mock.calls).toHaveLength(1); }); it("can override the return value for a single test", () => { testFunc.mockReturnValue("mock return value"); expect(testFunc()).toBe("mock return value"); expect(testFunc.mock.calls).toHaveLength(1); }); it("returns the original implementation when no overrides exist", () => { expect(testFunc()).toBe("original"); expect(testFunc.mock.calls).toHaveLength(1); });
जब हम jest.mock(''/cjsFunction'') को कॉल करते हैं, तो यह मॉड्यूल (फ़ाइल और उसके सभी निर्यात) को एक ऑटो-मॉक (दस्तावेज़) से बदल देता है। जब ऑटो-मॉक कहा जाता है, तो यह अपरिभाषित वापस आ जाएगा। हालाँकि, यह मॉक के कार्यान्वयन, रिटर्न वैल्यू और बहुत कुछ को ओवरराइड करने के तरीके प्रदान करेगा। आप जेस्ट मॉक फ़ंक्शंस दस्तावेज़ीकरण में इसके द्वारा प्रदान की गई सभी संपत्तियों और विधियों को देख सकते हैं।
हम मॉक के कार्यान्वयन को मूल मॉड्यूल के कार्यान्वयन पर स्वचालित रूप से सेट करने के लिए मॉक की मॉकइम्प्लीमेंटेशन() विधि का उपयोग कर सकते हैं। जेस्ट एक jest.requireActual() विधि प्रदान करता है जो हमेशा मूल मॉड्यूल को लोड करेगा, भले ही वर्तमान में इसका मजाक उड़ाया जा रहा हो।
मॉक कार्यान्वयन और रिटर्न मान प्रत्येक परीक्षण के बाद स्वचालित रूप से साफ़ हो जाते हैं, इसलिए हम जेस्ट के beforeEach() फ़ंक्शन में कॉलबैक फ़ंक्शन पास कर सकते हैं जो प्रत्येक परीक्षण से पहले मॉक के कार्यान्वयन को मूल कार्यान्वयन पर सेट करता है। फिर कोई भी परीक्षण जो अपना स्वयं का रिटर्न मान या कार्यान्वयन प्रदान करना चाहता है, वह परीक्षण निकाय के भीतर मैन्युअल रूप से ऐसा कर सकता है।
मान लें कि उपरोक्त कोड ने एकल फ़ंक्शन के बजाय एक ऑब्जेक्ट निर्यात किया था:
// cjsModule.js function testFunc() { return "original"; } module.exports = { testFunc: testFunc, };
तब हमारे परीक्षण इस तरह दिखेंगे:
const cjsModule = require("./cjsModule"); afterEach(() => { jest.restoreAllMocks(); }); it("can override the implementation for a single test", () => { jest .spyOn(cjsModule, "testFunc") .mockImplementation(() => "mock implementation"); expect(cjsModule.testFunc()).toBe("mock implementation"); expect(cjsModule.testFunc.mock.calls).toHaveLength(1); }); it("can override the return value for a single test", () => { jest.spyOn(cjsModule, "testFunc").mockReturnValue("mock return value"); expect(cjsModule.testFunc()).toBe("mock return value"); expect(cjsModule.testFunc.mock.calls).toHaveLength(1); }); it("returns the original implementation when no overrides exist", () => { expect(cjsModule.testFunc()).toBe("original"); }); it("can spy on calls while keeping the original implementation", () => { jest.spyOn(cjsModule, "testFunc"); expect(cjsModule.testFunc()).toBe("original"); expect(cjsModule.testFunc.mock.calls).toHaveLength(1); });
jest.spyOn() विधि जेस्ट को किसी ऑब्जेक्ट पर किसी विधि के लिए कॉल रिकॉर्ड करने और अपना स्वयं का प्रतिस्थापन प्रदान करने की अनुमति देती है। यह केवल ऑब्जेक्ट पर काम करता है, और हम इसका उपयोग कर सकते हैं क्योंकि हमारा मॉड्यूल एक ऑब्जेक्ट निर्यात कर रहा है जिसमें हमारा फ़ंक्शन शामिल है।
स्पाईऑन() विधि एक नकली है, इसलिए इसकी स्थिति को रीसेट किया जाना चाहिए। जेस्ट स्पाईऑन() दस्तावेज़, आफ्टरईच() कॉलबैक में jest.restoreAllMocks() का उपयोग करके स्थिति को रीसेट करने की अनुशंसा करता है, जैसा कि हमने ऊपर किया था। यदि हमने ऐसा नहीं किया, तो स्पाईऑन() बुलाए जाने के बाद अगले परीक्षण में मॉक अपरिभाषित वापस आ जाएगा।
ईएस मॉड्यूल में डिफ़ॉल्ट और नामित निर्यात हो सकते हैं:
// esmModule.js export default function () { return "original default"; } export function named() { return "original named"; }
उपरोक्त फ़ाइल के परीक्षण इस प्रकार होंगे:
import * as esmModule from "./esmModule"; afterEach(() => { jest.restoreAllMocks(); }); it("can override the implementation for a single test", () => { jest .spyOn(esmModule, "default") .mockImplementation(() => "mock implementation default"); jest .spyOn(esmModule, "named") .mockImplementation(() => "mock implementation named"); expect(esmModule.default()).toBe("mock implementation default"); expect(esmModule.named()).toBe("mock implementation named"); expect(esmModule.default.mock.calls).toHaveLength(1); expect(esmModule.named.mock.calls).toHaveLength(1); }); it("can override the return value for a single test", () => { jest.spyOn(esmModule, "default").mockReturnValue("mock return value default"); jest.spyOn(esmModule, "named").mockReturnValue("mock return value named"); expect(esmModule.default()).toBe("mock return value default"); expect(esmModule.named()).toBe("mock return value named"); expect(esmModule.default.mock.calls).toHaveLength(1); expect(esmModule.named.mock.calls).toHaveLength(1); }); it("returns the original implementation when no overrides exist", () => { expect(esmModule.default()).toBe("original default"); expect(esmModule.named()).toBe("original named"); });
यह कुछ प्रमुख अंतरों के साथ, लगभग पिछले कॉमनजेएस उदाहरण जैसा ही दिखता है।
सबसे पहले, हम अपने मॉड्यूल को नेमस्पेस आयात के रूप में आयात कर रहे हैं।
import * as esmModule from "./esmModule";
फिर जब हम डिफ़ॉल्ट निर्यात की जासूसी करना चाहते हैं, तो हम "डिफ़ॉल्ट" का उपयोग करते हैं:
jest .spyOn(esmModule, "default") .mockImplementation(() => "mock implementation default");
कभी-कभी किसी तृतीय-पक्ष पैकेज के साथ jest.spyOn() को कॉल करने का प्रयास करते समय, आपको नीचे दी गई त्रुटि मिलेगी:
TypeError: Cannot redefine property: useNavigate at Function.defineProperty ()
जब आप इस त्रुटि का सामना करते हैं, तो आपको उस पैकेज का मजाक उड़ाना होगा जो समस्या पैदा कर रहा है:
import * as reactRouterDOM from "react-router-dom"; // ADD THIS: jest.mock("react-router-dom", () => { const originalModule = jest.requireActual("react-router-dom"); return { __esModule: true, ...originalModule, }; }); afterEach(() => { jest.restoreAllMocks(); });
यह कोड मॉड्यूल को जेस्ट ईएस मॉड्यूल मॉक से बदल देता है जिसमें jest.mocks के फ़ैक्टरी पैरामीटर का उपयोग करके मॉड्यूल के सभी मूल गुण शामिल होते हैं। ES मॉड्यूल (दस्तावेज़) को मॉक करने के लिए jest.mock में फ़ैक्टरी पैरामीटर का उपयोग करते समय __esModule प्रॉपर्टी की आवश्यकता होती है।
यदि आप चाहें, तो आप फ़ैक्टरी पैरामीटर में एक व्यक्तिगत फ़ंक्शन को भी बदल सकते हैं। उदाहरण के लिए, यदि कोई उपभोक्ता राउटर संदर्भ के बाहर यूज़नेविगेट() को कॉल करता है, तो रिएक्ट राउटर एक त्रुटि देगा, इसलिए यदि हम चाहें तो हम संपूर्ण परीक्षण फ़ाइल में उस फ़ंक्शन को बदलने के लिए jest.mock() का उपयोग कर सकते हैं:
jest.mock("react-router-dom", () => { const originalModule = jest.requireActual("react-router-dom"); return { __esModule: true, ...originalModule, // Dummy that does nothing. useNavigate() { return function navigate(_location) { return; }; }, }; });
मुझे आशा है कि यह जानकारी मूल्यवान होगी क्योंकि आप अपने स्वयं के परीक्षण लिखते हैं। जब किसी परीक्षण में कोई कार्यान्वयन प्रदान नहीं किया जाता है, तो प्रत्येक ऐप को डिफ़ॉल्ट कार्यान्वयन पर वापस जाने में सक्षम होने से लाभ नहीं होगा। वास्तव में, कई ऐप्स संपूर्ण परीक्षण फ़ाइल के लिए एक ही मॉक का उपयोग करना चाहेंगे। हालाँकि, इस पोस्ट में दिखाई गई तकनीकें आपको अपने मज़ाक पर अच्छा नियंत्रण प्रदान करेंगी।
अगर मुझसे कुछ छूट गया है या ऐसा कुछ है जिसे मैंने इस पोस्ट में शामिल नहीं किया है जो यहां होना चाहिए तो मुझे बताएं।
अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।
Copyright© 2022 湘ICP备2022001581号-3