हिन्दी

मजबूत और विश्वसनीय सॉफ्टवेयर डेवलपमेंट के लिए अपनी टेस्टिंग रणनीति में मॉक फ़ंक्शंस का प्रभावी ढंग से उपयोग करना सीखें। यह गाइड व्यावहारिक उदाहरणों के साथ मॉक्स को कब, क्यों और कैसे लागू करना है, यह बताती है।

मॉक फ़ंक्शंस: डेवलपर्स के लिए एक विस्तृत गाइड

सॉफ्टवेयर डेवलपमेंट की दुनिया में, मजबूत और भरोसेमंद कोड लिखना सर्वोपरि है। इस लक्ष्य को प्राप्त करने के लिए गहन परीक्षण महत्वपूर्ण है। यूनिट टेस्टिंग, विशेष रूप से, अलग-अलग घटकों या फ़ंक्शंस को अलग-थलग करके परीक्षण करने पर ध्यान केंद्रित करती है। हालांकि, वास्तविक दुनिया के एप्लिकेशन में अक्सर जटिल निर्भरताएँ शामिल होती हैं, जिससे इकाइयों का पूरी तरह से अलग-थलग परीक्षण करना चुनौतीपूर्ण हो जाता है। यहीं पर मॉक फ़ंक्शंस काम आते हैं।

मॉक फ़ंक्शंस क्या हैं?

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

इसे इस तरह समझें: कल्पना कीजिए कि आप एक कार के इंजन (परीक्षण के तहत इकाई) का परीक्षण कर रहे हैं। इंजन कई अन्य घटकों पर निर्भर करता है, जैसे कि ईंधन इंजेक्शन प्रणाली और शीतलन प्रणाली। इंजन परीक्षण के दौरान वास्तविक ईंधन इंजेक्शन और शीतलन प्रणालियों को चलाने के बजाय, आप मॉक सिस्टम का उपयोग कर सकते हैं जो उनके व्यवहार का अनुकरण करते हैं। यह आपको इंजन को अलग करने और विशेष रूप से उसके प्रदर्शन पर ध्यान केंद्रित करने की अनुमति देता है।

मॉक फ़ंक्शंस इनके लिए शक्तिशाली उपकरण हैं:

मॉक फ़ंक्शंस का उपयोग कब करें

मॉक्स इन स्थितियों में सबसे उपयोगी होते हैं:

1. बाहरी निर्भरताओं वाली इकाइयों को अलग करना

जब आपकी परीक्षण के तहत इकाई बाहरी सेवाओं, डेटाबेस, एपीआई, या अन्य घटकों पर निर्भर करती है, तो परीक्षण के दौरान वास्तविक निर्भरताओं का उपयोग करने से कई समस्याएं हो सकती हैं:

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

2. जटिल इंटरैक्शन का परीक्षण

कुछ मामलों में, आपकी परीक्षण के तहत इकाई अन्य घटकों के साथ जटिल तरीकों से इंटरैक्ट कर सकती है। मॉक फ़ंक्शंस आपको इन इंटरैक्शन का अवलोकन और सत्यापन करने की अनुमति देते हैं।

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

3. त्रुटि स्थितियों का अनुकरण करना

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

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

4. एसिंक्रोनस कोड का परीक्षण

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

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

5. अनपेक्षित दुष्प्रभावों को रोकना

कभी-कभी, परीक्षण के दौरान एक वास्तविक फ़ंक्शन को कॉल करने से अनपेक्षित दुष्प्रभाव हो सकते हैं, जैसे कि डेटाबेस को संशोधित करना, ईमेल भेजना, या बाहरी प्रक्रियाओं को ट्रिगर करना। मॉक फ़ंक्शंस वास्तविक फ़ंक्शन को एक नियंत्रित सिमुलेशन के साथ बदलकर इन दुष्प्रभावों को रोकते हैं।

उदाहरण: आप एक ऐसे फ़ंक्शन का परीक्षण कर रहे हैं जो नए उपयोगकर्ताओं को स्वागत ईमेल भेजता है। एक मॉक ईमेल सेवा का उपयोग करके, आप यह सुनिश्चित कर सकते हैं कि ईमेल भेजने की कार्यक्षमता आपके परीक्षण सूट के चलने के दौरान वास्तविक उपयोगकर्ताओं को ईमेल नहीं भेजती है। इसके बजाय, आप यह सत्यापित कर सकते हैं कि फ़ंक्शन सही जानकारी के साथ ईमेल भेजने का प्रयास करता है।

मॉक फ़ंक्शंस का उपयोग कैसे करें

मॉक फ़ंक्शंस का उपयोग करने के विशिष्ट चरण आपके द्वारा उपयोग की जा रही प्रोग्रामिंग भाषा और परीक्षण ढांचे पर निर्भर करते हैं। हालाँकि, सामान्य प्रक्रिया में आमतौर पर निम्नलिखित चरण शामिल होते हैं:

  1. निर्भरताओं की पहचान करें: निर्धारित करें कि आपको किन बाहरी निर्भरताओं को मॉक करने की आवश्यकता है।
  2. मॉक ऑब्जेक्ट्स बनाएं: वास्तविक निर्भरताओं को बदलने के लिए मॉक ऑब्जेक्ट्स या फ़ंक्शंस बनाएं। इन मॉक्स में अक्सर called, returnValue, और callArguments जैसी प्रॉपर्टीज होंगी।
  3. मॉक व्यवहार को कॉन्फ़िगर करें: मॉक फ़ंक्शंस के व्यवहार को परिभाषित करें, जैसे कि उनके रिटर्न मान, त्रुटि की स्थिति, और कॉल काउंट।
  4. मॉक्स इंजेक्ट करें: अपनी परीक्षण के तहत इकाई में वास्तविक निर्भरताओं को मॉक ऑब्जेक्ट्स से बदलें। यह अक्सर डिपेंडेंसी इंजेक्शन का उपयोग करके किया जाता है।
  5. परीक्षण निष्पादित करें: अपना परीक्षण चलाएं और देखें कि परीक्षण के तहत इकाई मॉक फ़ंक्शंस के साथ कैसे इंटरैक्ट करती है।
  6. इंटरैक्शन सत्यापित करें: सत्यापित करें कि मॉक फ़ंक्शंस को अपेक्षित तर्कों, रिटर्न मानों और संख्या के साथ कॉल किया गया था।
  7. मूल कार्यक्षमता को पुनर्स्थापित करें: परीक्षण के बाद, मॉक ऑब्जेक्ट्स को हटाकर और वास्तविक निर्भरताओं पर वापस लौटकर मूल कार्यक्षमता को पुनर्स्थापित करें। यह अन्य परीक्षणों पर दुष्प्रभावों से बचने में मदद करता है।

विभिन्न भाषाओं में मॉक फ़ंक्शन के उदाहरण

यहां लोकप्रिय प्रोग्रामिंग भाषाओं और परीक्षण ढांचे में मॉक फ़ंक्शंस का उपयोग करने के उदाहरण दिए गए हैं:

जावास्क्रिप्ट जेस्ट के साथ

जेस्ट एक लोकप्रिय जावास्क्रिप्ट परीक्षण ढांचा है जो मॉक फ़ंक्शंस के लिए अंतर्निहित समर्थन प्रदान करता है।

// परीक्षण के लिए फ़ंक्शन
function fetchData(callback) {
  setTimeout(() => {
    callback('Data from server');
  }, 100);
}

// टेस्ट केस
test('fetchData calls callback with correct data', (done) => {
  const mockCallback = jest.fn();
  fetchData(mockCallback);

  setTimeout(() => {
    expect(mockCallback).toHaveBeenCalledWith('Data from server');
    done();
  }, 200);
});

इस उदाहरण में, jest.fn() एक मॉक फ़ंक्शन बनाता है जो वास्तविक कॉलबैक फ़ंक्शन की जगह लेता है। परीक्षण यह सत्यापित करता है कि मॉक फ़ंक्शन को toHaveBeenCalledWith() का उपयोग करके सही डेटा के साथ कॉल किया गया है।

मॉड्यूल का उपयोग करके अधिक उन्नत उदाहरण:

// user.js
import { getUserDataFromAPI } from './api';

export async function displayUserName(userId) {
  const userData = await getUserDataFromAPI(userId);
  return userData.name;
}

// api.js
export async function getUserDataFromAPI(userId) {
  // API कॉल का अनुकरण करें
  return new Promise(resolve => {
    setTimeout(() => {
      resolve({ id: userId, name: 'John Doe' });
    }, 50);
  });
}

// user.test.js
import { displayUserName } from './user';
import * as api from './api';

describe('displayUserName', () => {
  it('should display the user name', async () => {
    // getUserDataFromAPI फ़ंक्शन को मॉक करें
    const mockGetUserData = jest.spyOn(api, 'getUserDataFromAPI');
    mockGetUserData.mockResolvedValue({ id: 123, name: 'Mocked Name' });

    const userName = await displayUserName(123);
    expect(userName).toBe('Mocked Name');

    // मूल फ़ंक्शन को पुनर्स्थापित करें
    mockGetUserData.mockRestore();
  });
});

यहां, jest.spyOn का उपयोग ./api मॉड्यूल से आयातित getUserDataFromAPI फ़ंक्शन के लिए एक मॉक फ़ंक्शन बनाने के लिए किया जाता है। mockResolvedValue का उपयोग मॉक के रिटर्न मान को निर्दिष्ट करने के लिए किया जाता है। mockRestore यह सुनिश्चित करने के लिए आवश्यक है कि अन्य परीक्षण अनजाने में मॉक किए गए संस्करण का उपयोग न करें।

पाइथन pytest और unittest.mock के साथ

पाइथन मॉकिंग के लिए कई लाइब्रेरी प्रदान करता है, जिसमें unittest.mock (अंतर्निहित) और pytest-mock जैसी लाइब्रेरी शामिल हैं, जो pytest के साथ सरलीकृत उपयोग के लिए हैं।

# परीक्षण के लिए फ़ंक्शन
def get_data_from_api(url):
    # एक वास्तविक परिदृश्य में, यह एक API कॉल करेगा
    # सरलता के लिए, हम एक API कॉल का अनुकरण करते हैं
    if url == "https://example.com/api":
        return {"data": "API data"}
    else:
        return None

def process_data(url):
    data = get_data_from_api(url)
    if data:
        return data["data"]
    else:
        return "No data found"

# unittest.mock का उपयोग करके टेस्ट केस
import unittest
from unittest.mock import patch

class TestProcessData(unittest.TestCase):
    @patch('__main__.get_data_from_api') # मुख्य मॉड्यूल में get_data_from_api को बदलें
    def test_process_data_success(self, mock_get_data_from_api):
        # मॉक को कॉन्फ़िगर करें
        mock_get_data_from_api.return_value = {"data": "Mocked data"}

        # परीक्षण किए जा रहे फ़ंक्शन को कॉल करें
        result = process_data("https://example.com/api")

        # परिणाम की पुष्टि करें
        self.assertEqual(result, "Mocked data")
        mock_get_data_from_api.assert_called_once_with("https://example.com/api")

    @patch('__main__.get_data_from_api')
    def test_process_data_failure(self, mock_get_data_from_api):
        mock_get_data_from_api.return_value = None
        result = process_data("https://example.com/api")
        self.assertEqual(result, "No data found")

if __name__ == '__main__':
    unittest.main()

यह उदाहरण get_data_from_api फ़ंक्शन को एक मॉक के साथ बदलने के लिए unittest.mock.patch का उपयोग करता है। परीक्षण मॉक को एक विशिष्ट मान वापस करने के लिए कॉन्फ़िगर करता है और फिर यह सत्यापित करता है कि process_data फ़ंक्शन अपेक्षित परिणाम लौटाता है।

यहां pytest-mock का उपयोग करके वही उदाहरण है:

# pytest संस्करण
import pytest

def get_data_from_api(url):
    # एक वास्तविक परिदृश्य में, यह एक API कॉल करेगा
    # सरलता के लिए, हम एक API कॉल का अनुकरण करते हैं
    if url == "https://example.com/api":
        return {"data": "API data"}
    else:
        return None

def process_data(url):
    data = get_data_from_api(url)
    if data:
        return data["data"]
    else:
        return "No data found"


def test_process_data_success(mocker):
    mocker.patch('__main__.get_data_from_api', return_value={"data": "Mocked data"})
    result = process_data("https://example.com/api")
    assert result == "Mocked data"


def test_process_data_failure(mocker):
    mocker.patch('__main__.get_data_from_api', return_value=None)
    result = process_data("https://example.com/api")
    assert result == "No data found"

pytest-mock लाइब्रेरी एक mocker फिक्स्चर प्रदान करती है जो pytest परीक्षणों के भीतर मॉक्स के निर्माण और कॉन्फ़िगरेशन को सरल बनाती है।

जावा मॉकिटो के साथ

मॉकिटो जावा के लिए एक लोकप्रिय मॉकिंग फ्रेमवर्क है।

import org.junit.jupiter.api.Test;
import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

interface DataFetcher {
    String fetchData(String url);
}

class DataProcessor {
    private final DataFetcher dataFetcher;

    public DataProcessor(DataFetcher dataFetcher) {
        this.dataFetcher = dataFetcher;
    }

    public String processData(String url) {
        String data = dataFetcher.fetchData(url);
        if (data != null) {
            return "Processed: " + data;
        } else {
            return "No data";
        }
    }
}

public class DataProcessorTest {

    @Test
    public void testProcessDataSuccess() {
        // एक मॉक DataFetcher बनाएं
        DataFetcher mockDataFetcher = mock(DataFetcher.class);

        // मॉक को कॉन्फ़िगर करें
        when(mockDataFetcher.fetchData("https://example.com/api")).thenReturn("API Data");

        // मॉक के साथ DataProcessor बनाएं
        DataProcessor dataProcessor = new DataProcessor(mockDataFetcher);

        // परीक्षण किए जा रहे फ़ंक्शन को कॉल करें
        String result = dataProcessor.processData("https://example.com/api");

        // परिणाम की पुष्टि करें
        assertEquals("Processed: API Data", result);

        // सत्यापित करें कि मॉक को कॉल किया गया था
        verify(mockDataFetcher).fetchData("https://example.com/api");
    }

    @Test
    public void testProcessDataFailure() {
        DataFetcher mockDataFetcher = mock(DataFetcher.class);
        when(mockDataFetcher.fetchData("https://example.com/api")).thenReturn(null);

        DataProcessor dataProcessor = new DataProcessor(mockDataFetcher);
        String result = dataProcessor.processData("https://example.com/api");
        assertEquals("No data", result);
        verify(mockDataFetcher).fetchData("https://example.com/api");
    }
}

इस उदाहरण में, Mockito.mock() DataFetcher इंटरफ़ेस के लिए एक मॉक ऑब्जेक्ट बनाता है। when() का उपयोग मॉक के रिटर्न मान को कॉन्फ़िगर करने के लिए किया जाता है, और verify() का उपयोग यह सत्यापित करने के लिए किया जाता है कि मॉक को अपेक्षित तर्कों के साथ कॉल किया गया था।

मॉक फ़ंक्शंस का उपयोग करने के लिए सर्वोत्तम अभ्यास

मॉक फ़ंक्शंस के विकल्प

हालांकि मॉक फ़ंक्शंस एक शक्तिशाली उपकरण हैं, वे हमेशा सबसे अच्छा समाधान नहीं होते हैं। कुछ मामलों में, अन्य तकनीकें अधिक उपयुक्त हो सकती हैं:

निष्कर्ष

मॉक फ़ंक्शंस प्रभावी यूनिट परीक्षण लिखने के लिए एक आवश्यक उपकरण हैं, जो आपको इकाइयों को अलग करने, व्यवहार को नियंत्रित करने, त्रुटि की स्थितियों का अनुकरण करने और एसिंक्रोनस कोड का परीक्षण करने में सक्षम बनाते हैं। सर्वोत्तम प्रथाओं का पालन करके और विकल्पों को समझकर, आप अधिक मजबूत, विश्वसनीय और रखरखाव योग्य सॉफ्टवेयर बनाने के लिए मॉक फ़ंक्शंस का लाभ उठा सकते हैं। व्यापक और प्रभावी परीक्षण रणनीति बनाने के लिए प्रत्येक स्थिति के लिए सही परीक्षण तकनीक चुनने और ट्रेड-ऑफ पर विचार करना याद रखें, चाहे आप दुनिया के किसी भी हिस्से से निर्माण कर रहे हों।