javascript मस्टर के साथ मस्तक का नकली नहीं किया जा सकता है, और फ़ंक्शन कॉल का परीक्षण कर सकते हैं



unit-testing reactjs (1)

समस्या

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

भले ही आपके मूल कोड में आप केवल खोज mockSearch को mockSearch लिए मान देते mockSearch और मजाक के फोन करने के बाद ही आयात करते हैं, तो चश्मा का कहना है कि: Before instantiating a module, all of the modules it requested must be available

इसलिए, उस समय SearchContainer आयात किया जाता है, और बारी-बारी से आयात search , आपका mockSearch search चर अभी भी अनिर्धारित है।

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

फिर भी, mockSearch का काम, जिसे नकली समारोह द्वारा संदर्भित किया गया है, mock कॉल के साथ फहराया नहीं जाएगा। तो, प्रासंगिक कार्यों का क्रम कुछ ऐसा होगा:

  1. ./search.js लिए एक नकली कारखाना सेट करें
  2. सभी निर्भरताएं आयात करें, जो घटक को देने के लिए फ़ोक के लिए नकली कारखाना कहलाएगा
  3. mockSearch लिए एक मान असाइन करें

जब चरण 2 होता है, तो घटक को पास किए गए search फ़ंक्शन को अनिर्धारित नहीं किया जाएगा, और चरण 3 में असाइनमेंट को बदलने के लिए बहुत देर हो चुकी है।

उपाय

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

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

चूंकि अब आप जानबूझकर मजाक उड़ाते हैं, वास्तव में आयात के पहले होता है, एक तुच्छ दृष्टिकोण होगा:

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);
});

वास्तव में, आप इसे बदलना चाहते हैं:

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

साथ में:

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

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

अतिरिक्त नोट

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

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

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

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

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

मेरी खोज। 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 हो रही थी कि jest.mock काम कैसे करें, क्योंकि इसके लिए jest.mock को jest.mock लिए jest.mock किया गया है।

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

यदि मैं मजाक का हिस्सा बदलता हूं, तो एक चर का उपयोग करने के लिए:

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

मुझे यह त्रुटि मिलती है:

TypeError: (0, _search.search) फ़ंक्शन नहीं है

जो भी मैं jest.fn तक पहुंच प्राप्त करने और jest.fn का परीक्षण करने की कोशिश करता jest.fn , मैं इसे काम नहीं कर सकता।

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