2017-07-14 20 views
14

सबसे अच्छा तरीका है सही ढंग से निम्न उदाहरण उपहास करने के लिए क्या है का उपयोग करते हुए एक ही मॉड्यूल में कार्यों उपहास करने के लिए?कैसे हंसी

समस्या यह है कि आयात समय के बाद, foo मूल अनमॉक bar के संदर्भ को संदर्भित करता है।

module.js:

export function bar() { 
    return 'bar'; 
} 

export function foo() { 
    return `I am foo. bar is ${bar()}`; 
} 

module.test.js:

import * as module from '../src/module'; 

describe('module',() => { 
    let barSpy; 

    beforeEach(() => { 
     barSpy = jest.spyOn(
      module, 
      'bar' 
     ).mockImplementation(jest.fn()); 
    }); 


    afterEach(() => { 
     barSpy.mockRestore(); 
    }); 

    it('foo',() => { 
     console.log(jest.isMockFunction(module.bar)); // outputs true 

     module.bar.mockReturnValue('fake bar'); 

     console.log(module.bar()); // outputs 'fake bar'; 

     expect(module.foo()).toEqual('I am foo. bar is fake bar'); 
     /** 
     * does not work! we get the following: 
     * 
     * Expected value to equal: 
     * "I am foo. bar is fake bar" 
     * Received: 
     * "I am foo. bar is bar" 
     */ 
    }); 
}); 

धन्यवाद!

संपादित करें: मैं बदल सकता है:

export function foo() { 
    return `I am foo. bar is ${bar()}`; 
} 

export function foo() { 
    return `I am foo. bar is ${exports.bar()}`; 
} 

के लिए, लेकिन यह पी है। हर जगह करने के लिए मेरी राय में बदसूरत:/

उत्तर

2

fwiw, समाधान मैं पर बसे dependency injection उपयोग करने के लिए, एक डिफ़ॉल्ट तर्क की स्थापना द्वारा किया गया था।

तो मैं बदल जाएगा

export function bar() { 
    return 'bar'; 
} 

export function foo() { 
    return `I am foo. bar is ${bar()}`; 
} 

को
export function bar() { 
    return 'bar'; 
} 

export function foo (_bar = bar) { 
    return `I am foo. bar is ${_bar()}`; 
} 

यह मेरा घटक के एपीआई के लिए एक को तोड़ने परिवर्तन नहीं है, और मैं आसानी से निम्नलिखित

करके अपने परीक्षण में बार ओवरराइड कर सकते हैं
import { foo, bar } from '../src/module'; 

describe('module',() => { 
    it('foo',() => { 
     const dummyBar = jest.fn().mockReturnValue('fake bar'); 
     expect(foo(dummyBar)).toEqual('I am foo. bar is fake bar'); 
    }); 
}); 

इसका थोड़ा सा अच्छा परीक्षण कोड भी अग्रणी होने का लाभ है :)

+0

मैं आम तौर पर, निर्भरता इंजेक्शन के एक प्रशंसक नहीं हूँ जब से तुम अनुमति दे रहे हैं कोड कैसे लिखा जाता है बदलने के लिए परीक्षण। ऐसा कहा जा रहा है, यह वर्तमान उच्च वोट वाले उत्तर से बेहतर है जो बहुत बदसूरत है – Sean

9

समस्या यह है कि आप बार के हल होने के दायरे की अपेक्षा कैसे करते हैं।

एक ओर, module.js में आप दो कार्यों को निर्यात करते हैं (इन दो कार्यों को रखने वाली वस्तु के बजाय)। जिस तरह से मॉड्यूल निर्यात किए जाते हैं, निर्यातित चीजों के कंटेनर का संदर्भ exports जैसा आपने उल्लेख किया है।

दूसरी तरफ, आप अपने निर्यात को संभालने वाले ऑब्जेक्ट (module) को इन कार्यों को रखने वाले ऑब्जेक्ट की तरह और अपने फ़ंक्शन (फ़ंक्शन बार) को प्रतिस्थापित करने का प्रयास करते हैं।

आप अपने foo कार्यान्वयन को बारीकी से देखें तो आप वास्तव में बार कार्य करने के लिए एक निश्चित संदर्भ पकड़े हुए हैं।

जब आपको लगता है कि आप एक नया जिसमें हाल ही में वास्तव में अपने module.test.js

के दायरे में संदर्भ प्रतिलिपि प्रतिस्थापित foo वास्तव में आप बार के दूसरे संस्करण का उपयोग करने के साथ बार समारोह की जगह दो संभावनाएं:

  1. module.js में, एक वर्ग या एक उदाहरण निर्यात दोनों foo और बार विधि पकड़े:

    module.js:

    export class MyModule { 
        function bar() { 
        return 'bar'; 
        } 
    
        function foo() { 
        return `I am foo. bar is ${this.bar()}`; 
        } 
    } 
    

    नोट foo विधि में इस कीवर्ड का उपयोग।

    Module.test.js:

    import { MyModule } from '../src/module' 
    
    describe('MyModule',() => { 
        //System under test : 
        const sut:MyModule = new MyModule(); 
    
        let barSpy; 
    
        beforeEach(() => { 
         barSpy = jest.spyOn(
          sut, 
          'bar' 
        ).mockImplementation(jest.fn()); 
        }); 
    
    
        afterEach(() => { 
         barSpy.mockRestore(); 
        }); 
    
        it('foo',() => { 
         sut.bar.mockReturnValue('fake bar'); 
         expect(sut.foo()).toEqual('I am foo. bar is fake bar'); 
        }); 
    }); 
    
  2. जैसे तुमने कहा, वैश्विक exports कंटेनर में वैश्विक संदर्भ पुनर्लेखन।यह एक अनुशंसित तरीका नहीं है क्योंकि आप अन्य परीक्षणों में अजीब व्यवहार पेश करेंगे यदि आप अपने शुरुआती राज्य में निर्यात को सही तरीके से रीसेट नहीं करते हैं।

1

एक वैकल्पिक समाधान मॉड्यूल को अपनी कोड फ़ाइल में आयात कर रहा है और सभी निर्यातित इकाइयों के आयातित उदाहरण का उपयोग कर सकता है। इस तरह:

import * as thisModule from './module'; 

export function bar() { 
    return 'bar'; 
} 

export function foo() { 
    return `I am foo. bar is ${thisModule.bar()}`; 
} 

अब, मजाक bar वास्तव में आसान है क्योंकि foo भी bar का निर्यात उदाहरण उपयोग कर रहा है:

import * as module from '../src/module'; 

describe('module',() => { 
    it('foo',() => { 
     spyOn(module, 'bar').and.returnValue('fake bar'); 
     expect(module.foo()).toEqual('I am foo. bar is fake bar'); 
    }); 
}); 

अपने स्वयं के कोड में मॉड्यूल आयात कर रहा है अजीब लगता है, लेकिन कारण ES6 के चक्रीय आयात के लिए समर्थन, यह वास्तव में आसानी से काम करता है।

0

यदि आप अपने निर्यात को परिभाषित करते हैं तो आप निर्यात कार्यों के हिस्से के रूप में अपने कार्यों का संदर्भ दे सकते हैं। फिर आप व्यक्तिगत रूप से अपने मैक्स में कार्यों को ओवरराइट कर सकते हैं। यह इस कारण है कि आयात संदर्भ के रूप में कैसे काम करता है, प्रतिलिपि नहीं।

module.js:

exports.bar() => { 
    return 'bar'; 
} 

exports.foo() => { 
    return `I am foo. bar is ${exports.bar()}`; 
} 

module.test.js:

describe('MyModule',() => { 

    it('foo',() => { 
    let module = require('./module') 
    module.bar = jest.fn(()=>{return 'fake bar'}) 

    expect(module.foo()).toEqual('I am foo. bar is fake bar'); 
    }); 

}) 
संबंधित मुद्दे