javascript - नकल - पेपर में चीटिंग करने के तरीके




ईएस 6 मॉड्यूल के आयात का मजाक कैसे उड़ाया जाए? (4)

@ vdloo का उत्तर मुझे सही दिशा में ले गया, लेकिन दोनों समान "निर्यात" और ES6 मॉड्यूल "निर्यात" कीवर्ड का एक ही फ़ाइल में एक साथ उपयोग करने से मेरे लिए काम नहीं किया (वेबपैक v2 या बाद में शिकायत करता है)। इसके बजाय, मैं एक डिफ़ॉल्ट (नामित वैरिएबल) निर्यात का उपयोग कर रहा हूं, जो मॉड्यूल निर्यात नाम के सभी व्यक्ति को लपेटता है और फिर मेरी परीक्षण फ़ाइल में डिफ़ॉल्ट निर्यात का आयात करता है। मैं मोचा / सिनॉन और स्टबिंग के साथ निम्नलिखित निर्यात सेटअप का उपयोग कर रहा हूं, बिना आवश्यकता के ठीक से काम करना, आदि:

// MyModule.js
let MyModule;

export function myfunc2() { return 2; }
export function myfunc1() { return MyModule.myfunc2(); }

export default MyModule = {
  myfunc1,
  myfunc2
}

// tests.js
import MyModule from './MyModule'

describe('MyModule', () => {
  const sandbox = sinon.sandbox.create();
  beforeEach(() => {
    sandbox.stub(MyModule, 'myfunc2').returns(4);
  });
  afterEach(() => {
    sandbox.restore();
  });
  it('myfunc1 is a proxy for myfunc2', () => {
    expect(MyModule.myfunc1()).to.eql(4);
  });
});

मेरे पास निम्नलिखित ईएस 6 मॉड्यूल हैं:

network.js

export function getDataFromServer() {
  return ...
}

widget.js

import { getDataFromServer } from 'network.js';

export class Widget() {
  constructor() {
    getDataFromServer("dataForWidget")
    .then(data => this.render(data));
  }

  render() {
    ...
  }
}

मैं getDataFromServer एक नकली उदाहरण के साथ विजेट का परीक्षण करने के लिए एक रास्ता खोज रहा हूँ। यदि मैं ES6 मॉड्यूल के बजाय अलग <script> s का उपयोग करता हूं, जैसे कर्म में, मैं अपना परीक्षण लिख सकता हूं जैसे:

describe("widget", function() {
  it("should do stuff", function() {
    let getDataFromServer = spyOn(window, "getDataFromServer").andReturn("mockData")
    let widget = new Widget();
    expect(getDataFromServer).toHaveBeenCalledWith("dataForWidget");
    expect(otherStuff).toHaveHappened();
  });
});

हालांकि, अगर मैं एक ब्राउज़र के बाहर व्यक्तिगत रूप से ईएस 6 मॉड्यूल का परीक्षण कर रहा हूं (जैसे मोचा + बाबेल के साथ), तो मैं कुछ इस तरह लिखूंगा:

import { Widget } from 'widget.js';

describe("widget", function() {
  it("should do stuff", function() {
    let getDataFromServer = spyOn(?????) // How to mock?
    .andReturn("mockData")
    let widget = new Widget();
    expect(getDataFromServer).toHaveBeenCalledWith("dataForWidget");
    expect(otherStuff).toHaveHappened();
  });
});

ठीक है, लेकिन अब getDataFromServer window में उपलब्ध नहीं है (अच्छी तरह से, वहाँ कोई window नहीं है), और मैं सीधे widget.js के दायरे में सामान को इंजेक्ट करने का तरीका नहीं जानता।

अब मुझे यहां से कहां जाना है?

  1. क्या widget.js के दायरे को एक्सेस करने का कोई तरीका है, या कम से कम इसके आयात को मेरे स्वयं के कोड से बदल सकते हैं?
  2. यदि नहीं, तो मैं Widget को कैसे परीक्षण योग्य बना सकता हूं?

सामान मैंने माना:

ए। मैनुअल निर्भरता इंजेक्शन।

widget.js से सभी आयात widget.js और कॉल करने वाले से widget.js प्रदान करने की अपेक्षा करें।

export class Widget() {
  constructor(deps) {
    deps.getDataFromServer("dataForWidget")
    .then(data => this.render(data));
  }
}

मैं इस तरह से विजेट के सार्वजनिक इंटरफ़ेस को गड़बड़ाने और कार्यान्वयन विवरणों को उजागर करने के साथ बहुत असहज हूं। नही जाओ।

ख। आयात को बेनकाब करने के लिए उन्हें नकली करने की अनुमति दें।

कुछ इस तरह:

import { getDataFromServer } from 'network.js';

export let deps = {
  getDataFromServer
};

export class Widget() {
  constructor() {
    deps.getDataFromServer("dataForWidget")
    .then(data => this.render(data));
  }
}

फिर:

import { Widget, deps } from 'widget.js';

describe("widget", function() {
  it("should do stuff", function() {
    let getDataFromServer = spyOn(deps.getDataFromServer)  // !
      .andReturn("mockData");
    let widget = new Widget();
    expect(getDataFromServer).toHaveBeenCalledWith("dataForWidget");
    expect(otherStuff).toHaveHappened();
  });
});

यह कम आक्रामक है, लेकिन मुझे प्रत्येक मॉड्यूल के लिए बहुत सारे बॉयलरप्लेट लिखने की आवश्यकता है, और हर समय deps.getDataFromServer बजाय getDataFromServer का उपयोग करने का एक जोखिम है। मैं इसे लेकर असहज हूं, लेकिन यह मेरा अब तक का सबसे अच्छा विचार है।


@carpeliam सही है लेकिन ध्यान दें कि यदि आप किसी मॉड्यूल में किसी फ़ंक्शन की जासूसी करना चाहते हैं और उस फ़ंक्शन को कॉल करने वाले मॉड्यूल में किसी अन्य फ़ंक्शन का उपयोग करना चाहते हैं, तो आपको उस फ़ंक्शन को निर्यात नाम के भाग के रूप में कॉल करने की आवश्यकता है अन्यथा जासूस का उपयोग नहीं किया जाएगा।

गलत उदाहरण:

// mymodule.js

export function myfunc2() {return 2;}
export function myfunc1() {return myfunc2();}

// tests.js
import * as mymodule

describe('tests', () => {
    beforeEach(() => {
        spyOn(mymodule, 'myfunc2').and.returnValue = 3;
    });

    it('calls myfunc2', () => {
        let out = mymodule.myfunc1();
        // out will still be 2
    });
});

सही उदाहरण:

export function myfunc2() {return 2;}
export function myfunc1() {return exports.myfunc2();}

// tests.js
import * as mymodule

describe('tests', () => {
    beforeEach(() => {
        spyOn(mymodule, 'myfunc2').and.returnValue = 3;
    });

    it('calls myfunc2', () => {
        let out = mymodule.myfunc1();
        // out will be 3 which is what you expect
    });
});

मैंने इस वाक्य रचना को काम करते पाया है:

मेरा मॉड्यूल:

// mymod.js
import shortid from 'shortid';

const myfunc = () => shortid();
export default myfunc;

मेरे मॉड्यूल का परीक्षण कोड:

// mymod.test.js
import myfunc from './mymod';
import shortid from 'shortid';

jest.mock('shortid');

describe('mocks shortid', () => {
  it('works', () => {
    shortid.mockImplementation(() => 1);
    expect(myfunc()).toEqual(1);
  });
});

डॉक्टर को देखें।


मैंने एक पुस्तकालय लागू किया है जो किसी भी स्पष्ट निर्भरता इंजेक्शन के बारे में जानने के लिए मूल वर्ग की आवश्यकता के बिना टाइपस्क्रिप्ट श्रेणी के आयात के रन-टाइम मॉकिंग के मुद्दे को हल करने का प्रयास करता है।

पुस्तकालय import * as सिंटैक्स के import * as में import * as का उपयोग करता है और फिर मूल निर्यात वस्तु को स्टब क्लास से बदल देता है। यह प्रकार की सुरक्षा को बरकरार रखता है इसलिए आपके परीक्षण संकलन समय पर टूट जाएंगे यदि विधि का नाम इसी परीक्षण को अपडेट किए बिना अपडेट किया गया हो।

यह पुस्तकालय यहां पाया जा सकता है: ts-mock-imports






ecmascript-6