हार्ड कोडित ऑब्जेक्ट के साथ विधि का मजाक कैसे करें?


11

मैं एक ऐसे अनुप्रयोग पर काम कर रहा हूं जिसमें कई परतें हैं। स्क्रीन पर डेटा दिखाने के लिए डेटा स्रोत, व्यावसायिक तर्क से डेटा को हेरफेर करने के लिए डेटा स्रोत, व्यापार तर्क को पुनः प्राप्त करने और सहेजने के लिए डेटा एक्सेस परत।

मैं व्यापार तर्क परत की इकाई परीक्षण भी कर रहा हूं। एकमात्र आवश्यकता व्यवसाय परत तर्क के प्रवाह का परीक्षण करना है। इसलिए मैं डेटा एक्सेस लेयर को मॉक करने के लिए Moq फ्रेमवर्क का उपयोग करता हूं और MS MS यूनिट के साथ बिजनेस लॉजिक लेयर का परीक्षण करता हूं।

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

मैं एक समस्या का सामना कर रहा हूं जब मैं व्यवसाय तर्क पद्धति का परीक्षण करने की कोशिश कर रहा हूं। वह विधि कुछ काम करती है और एक ऑब्जेक्ट बनाती है और इसे डेटा एक्सेस लेयर में पास करती है। जब मैं उस डेटा ऐक्सेस लेयर विधि का मखौल उड़ाने की कोशिश कर रहा हूँ तो यह सफलतापूर्वक नकली नहीं हो सकता।

यहां मैं अपनी समस्या दिखाने के लिए एक डेमो कोड बनाने की कोशिश कर रहा हूं।

नमूना:

public class Employee
{
    public string Name { get; set; }
}

डेटा एक्सेस परत:

public interface IDal
{
    string GetMessage(Employee emp);
}

public class Dal : IDal
{
    public string GetMessage(Employee emp)
    {
        // Doing some data source access work...

        return string.Format("Hello {0}", emp.Name);
    }
}

व्यापार तर्क परत:

public interface IBll
{
    string GetMessage();
}

public class Bll : IBll
{
    private readonly IDal _dal;

    public Bll(IDal dal)
    {
        _dal = dal;
    }

    public string GetMessage()
    {
        // Object creating inside business logic method.
        Employee emp = new Employee(); 

        string msg = _dal.GetMessage(emp);
        return msg;
    }
}

अध्याय परीक्षा:

[TestMethod]
    public void Is_GetMessage_Return_Proper_Result()
    {
        // Arrange.
        Employee emp = new Employee; // New object.

        Mock<IDal> mockDal = new Mock<IDal>();
        mockDal.Setup(d => d.GetMessage(emp)).Returns("Hello " + emp.Name);

        IBll bll = new Bll(mockDal.Object);

        // Act.

        // This will create another employee object inside the 
        // business logic method, which is different from the 
        // object which I have sent at the time of mocking.
        string msg = bll.GetMessage(); 

        // Assert.
        Assert.AreEqual("Hello arnab", msg);
    }

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

उस मामले में कैसे डिजाइन करें ताकि मैं समस्या को हल कर सकूं?


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

जवाबों:


12

Employeeका उपयोग करके सीधे एक वस्तु बनाने के बजाय new, आपकी कक्षा Bllइसके लिए एक EmployeeFactoryवर्ग का उपयोग कर सकती है , एक विधि के साथ createInstance, जिसे निर्माता के माध्यम से इंजेक्ट किया जाता है:

 class EmployeeFactory : IEmployeeFactory
 {
       public Employee createInstance(){return new Employee();}
 }

कंस्ट्रक्टर को फैक्ट्री ऑब्जेक्ट को एक इंटरफेस के माध्यम से लेना चाहिए IEmployeeFactory, ताकि आप "असली" फैक्ट्री को आसानी से मॉक फैक्ट्री द्वारा बदल सकें।

public class Bll : IBll
{
    private readonly IDal _dal;
    private readonly IEmployeeFactory _employeeFactory;

    public Bll(IDal dal, IEmployeeFactory employeeFactory)
    {
        _dal = dal;
        _employeeFactory=employeeFactory;
    }

    public string GetMessage()
    {
        // Object creating inside business logic method
        // *** using a factory ***
        Employee emp = _employeeFactory.createObject(); 
        // ...
    }
    //...
}

मॉक फैक्ट्री Employeeआपको अपने परीक्षण के लिए किसी भी प्रकार की वस्तु प्रदान कर सकती है (उदाहरण के लिए, createInstanceहमेशा उसी वस्तु को वापस कर सकती है):

 class MockEmployeeFactory : IEmployeeFactory
 {
       private Employee _emp;

       public MockEmployeeFactory()
       {
          _emp = new Employee();
          // add any kind of special initializing here for testing purposes
       }

       public Employee createInstance()
       {
          // just for testing, return always the same object
          return _emp;
       }
 }

अब इस मॉक को अपने टेस्ट में इस्तेमाल करके ट्रिक करना चाहिए।


क्या आप मुझे एक कोड उदाहरण दे सकते हैं, ताकि मैं आपके सिद्धांत की कल्पना कर सकूं?
DeveloperArnab

@DeveloperArnab: मेरा संपादन देखें।
डॉक ब्राउन

बहुत मददगार ...
DeveloperArnab

4

मैं इसे परीक्षण करने के लिए एकल इकाई के रूप में मानूंगा।

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

जाहिर है इसका मतलब है कि आपको नकली विधि के लिए कस्टम तर्क प्रदान करने की आवश्यकता है। उन्नत तर्क अक्सर "एक्स रिटर्न वाई के लिए" प्रकार के मोक्स के साथ परीक्षण नहीं किया जा सकता है।

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


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

@DeveloperArnab: ऑब्जेक्ट अलग-अलग होंगे, लेकिन उनके पास ज्ञात सामग्री होगी। तो आपको बस इतना करना चाहिए कि वस्तु पहचान के बजाय नकली करना कस्टम तुलना करें।
Jan Hudec

@DeveloperArnab: यदि आप Employeeपरीक्षणों में विभिन्न ऑब्जेक्ट को इंजेक्ट करते हैं , तो आप उस कोड का परीक्षण नहीं करेंगे जो सामान्य रूप से इसे बनाता है। इसलिए आपको इसे बदलना नहीं चाहिए।
Jan Hudec

0

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

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.