2016-09-22 12 views
14

मैं create-app-component का उपयोग करके एक प्रोजेक्ट बनाता हूं, जो बिल्ड स्क्रिप्ट्स (बेबेल, वेबपैक, जेस्ट) के साथ एक नया ऐप कॉन्फ़िगर करता है।जेस्ट के साथ मॉड्यूल का नकल नहीं कर सकता है, और टेस्ट फ़ंक्शन कॉल

मैंने एक प्रतिक्रिया घटक लिखा है जिसे मैं परीक्षण करने की कोशिश कर रहा हूं। घटक को एक और जावास्क्रिप्ट फ़ाइल की आवश्यकता होती है, जिसमें फ़ंक्शन का खुलासा होता है।

मेरे search.js फ़ाइल

export { 
    search, 
} 

function search(){ 
    // does things 
    return Promise.resolve('foo') 
} 

मेरे प्रतिक्रिया घटक:

import React from 'react' 
import { search } from './search.js' 
import SearchResults from './SearchResults' 

export default SearchContainer { 
    constructor(){ 
    this.state = { 
     query: "hello world" 
    } 
    } 

    componentDidMount(){ 
    search(this.state.query) 
     .then(result => { this.setState({ result, })}) 
    } 

    render() { 
    return <SearchResults 
      result={this.state.result} 
      /> 
    } 
} 

मेरी इकाई परीक्षण में, मैं यह देखना होगा कि विधि search सही तर्क के साथ बुलाया गया था चाहते हैं।

मेरे परीक्षण है कि कुछ इस तरह दिखाई:

import React from 'react'; 
import { shallow } from 'enzyme'; 
import should from 'should/as-function'; 

import SearchResults from './SearchResults'; 

let mockPromise; 

jest.mock('./search.js',() => { 
    return { search: jest.fn(() => mockPromise)}; 
}); 

import SearchContainer from './SearchContainer'; 

describe('<SearchContainer />',() => { 
    it('should call the search module',() => { 
    const result = { foo: 'bar' } 
    mockPromise = Promise.resolve(result); 
    const wrapper = shallow(<SearchContainer />); 

    wrapper.instance().componentDidMount(); 

    mockPromise.then(() => { 
     const searchResults = wrapper.find(SearchResults).first(); 
     should(searchResults.prop('result')).equal(result); 
    })  
    }) 
}); 

मैं पहले से ही एक कठिन समय jest.mock काम करने के लिए कैसे, क्योंकि यह चर mock से उपसर्ग होना करने की आवश्यकता है यह पता लगाने के लिए था।

लेकिन अगर मैं search विधि के लिए तर्कों का परीक्षण करना चाहता हूं, तो मुझे अपने परीक्षणों में मॉक किए गए फ़ंक्शन को उपलब्ध कराने की आवश्यकता है।

अगर मैं मजाक भाग को बदलने, एक चर का उपयोग करें:

TypeError: (0 , _search.search) is not a function

जो कुछ भी मैं कोशिश jest.fn की पहुंच है और तर्क का परीक्षण, मैं करने के लिए:

const mockSearch = jest.fn(() => mockPromise) 
jest.mock('./search.js',() => { 
    return { search: mockSearch}; 
}); 

मैं इस त्रुटि मिलती है इसे काम नहीं कर सकता

मैं क्या गलत कर रहा हूं?

उत्तर

24

समस्या

कारण आप उस त्रुटि हो रही है कि कैसे विभिन्न कार्यों फहराया जाता है के साथ क्या करना है।

हालांकि अपने मूल कोड में आप केवल आयात SearchContainerके बादmockSearch के लिए एक मूल्य बताए और हंसी के mock, कि बाहर specs बिंदु बुला: Before instantiating a module, all of the modules it requested must be available

इसलिए, SearchContainer आयात किया गया है, और बदले में आयात search, आपके mockSearch चर अभी भी अपरिभाषित है।

कोई यह अजीब लगता है, क्योंकि यह प्रतीत होता है कि search.js अभी तक मजाक नहीं है, और इसलिए मॉकिंग बिल्कुल काम नहीं करेगा। सौभाग्य से, (बेबेल-) जेस्ट ने mock पर कॉल उठाना सुनिश्चित किया है और इसी तरह के कार्यों को भी आयात से उच्च पर काम करना है, ताकि मॉकिंग काम करे।

फिर भी, mockSearch का असाइनमेंट, जिसे मॉक के फ़ंक्शन द्वारा संदर्भित किया गया है, को mock कॉल से नहीं जोड़ा जाएगा।तो, प्रासंगिक आपरेशन के आदेश हो जाएगा की तरह कुछ:

  1. ./search.js
  2. आयात सभी निर्भरता के लिए एक नकली कारखाना है, जो एक समारोह के लिए नकली कारखाने कॉल करेंगे घटक
  3. निरुपित एक मूल्य देने के लिए सेट करें mockSearch

जब चरण 2 होता है, search समारोह घटक के लिए पारित अपरिभाषित किया जाएगा, और चरण 3 पर काम है कि बदलने के लिए बहुत देर हो चुकी है।

समाधान

आप mock कॉल का हिस्सा (जैसे कि यह भी फहराया जाएगा) के रूप में नकली समारोह बनाते हैं, तो उसे मान्य मान जब वह अपने जल्दी के रूप में, घटक मॉड्यूल द्वारा आयातित है होगा उदाहरण दिखाता है।

जैसा कि आपने बताया, समस्या तब शुरू होती है जब आप अपने परीक्षणों में मॉक किए गए फ़ंक्शन को उपलब्ध करना चाहते हैं। इसके लिए एक स्पष्ट समाधान है: मॉड्यूल को अलग से आयात करें जिसे आपने पहले से ही मजाक कर दिया है।

जब से तुम अब हंसी मजाक पता वास्तव में आयात से पहले होता है, एक छोटी सी दृष्टिकोण होगा:

import { search } from './search.js'; 

के साथ:

const { search } = require.requireMock('./search.js'); 

import { search } from './search.js'; // This will actually be the mock 

jest.mock('./search.js',() => { 
    return { search: jest.fn(() => mockPromise) }; 
}); 

[...] 

beforeEach(() => { 
    search.mockClear(); 
}); 

it('should call the search module',() => { 
    [...] 

    expect(search.mock.calls.length).toBe(1); 
    expect(search.mock.calls[0]).toEqual(expectedArgs); 
}); 

वास्तव में, आप को बदलने के लिए चाहते हो सकता है

इससे कोई कार्यात्मक अंतर नहीं होना चाहिए, लेकिन आप जो कुछ और कर रहे हैं वह कर सकते हैं यह (और फ्लो जैसे प्रकार-जांच प्रणाली का उपयोग करने में किसी को भी मदद करनी चाहिए, इसलिए ऐसा नहीं लगता कि आप मूल search पर नकली फ़ंक्शंस को कॉल करने का प्रयास कर रहे हैं)। क्या आपका उपहास करने की जरूरत है एक मॉड्यूल के ही डिफ़ॉल्ट निर्यात है अगर

अतिरिक्त नोट

यह सब केवल सख्ती से आवश्यक है। अन्यथा (जैसा कि @PublicJorn इंगित करता है), आप परीक्षणों में विशिष्ट प्रासंगिक सदस्य को फिर से असाइन कर सकते हैं, जैसे:

import * as search from './search.js'; 

beforeEach(() => { 
    search.search = jest.fn(() => mockPromise); 
}); 
+0

इस बहुत विस्तृत प्रतिक्रिया के लिए धन्यवाद। मैं निश्चित रूप से आपके समाधान का प्रयास करूंगा। – ghusse

+0

जबकि पिछले समाधान तकनीकी रूप से काम करना चाहिए (और मुझे अंत में यह भी पता चला कि क्यों 'var' आवश्यक था), अब मैंने जवाब को बहुत कम बदसूरत, आईएमओ का उपयोग करने के लिए संपादित किया है। आपकी मदद के लिए – Tomty

+0

धन्यवाद। दूसरे समाधान के साथ, मुझे एक त्रुटि मिलती है 'खोज की संपत्ति खोज सेट नहीं कर सकती'। पहला समाधान काम करता है: मुझे lib को आयात करने और सभी के लिए एक बार जस्ट कॉल करने की आवश्यकता है (पहले ट्रिगर में नहीं)। – ghusse

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