अन-इंजेक्शन कोड का परीक्षण कैसे करें?


13

इसलिए मेरे पास अपने सिस्टम पर उपयोग में आने वाला कोड निम्नलिखित है। वर्तमान में हम इकाई परीक्षण पूर्वव्यापी तरीके से लिख रहे हैं (मेरे तर्क से पहले कभी भी बेहतर नहीं था), लेकिन मैं यह नहीं देखता कि यह कैसे परीक्षण योग्य होगा?

public function validate($value, Constraint $constraint)
{
    $searchEntity = EmailAlertToSearchAdapter::adapt($value);

    $queryBuilder = SearcherFactory::getSearchDirector($searchEntity->getKeywords());
    $adapter = new SearchEntityToQueryAdapter($queryBuilder, $searchEntity);
    $query = $adapter->setupBuilder()->build();

    $totalCount = $this->advertType->count($query);

    if ($totalCount >= self::MAXIMUM_MATCHING_ADS) {
        $this->context->addViolation(
            $constraint->message
        );
    }
}

वैचारिक रूप से यह किसी भी भाषा पर लागू होना चाहिए, लेकिन मैं PHP का उपयोग कर रहा हूं। कोड केवल एक Searchऑब्जेक्ट के आधार पर एक इलास्टिक खोज क्वेरी ऑब्जेक्ट बनाता है , जो बदले में एक EmailAlertऑब्जेक्ट से निर्मित होता है । ये Searchऔर EmailAlertकेवल POPO के हैं।

मेरी समस्या यह है कि मैं नहीं दिख रहा है मैं कैसे बाहर नकली कर सकते हैं SearcherFactory(जो स्थिर विधि का उपयोग करता), और न ही SearchEntityToQueryAdapterहै, जिसमें से परिणाम की जरूरत है SearcherFactory::getSearchDirector औरSearch उदाहरण। मैं किसी ऐसी चीज़ को कैसे इंजेक्ट कर सकता हूं जो किसी पद्धति के भीतर परिणामों से निर्मित होती है? हो सकता है कि कुछ डिज़ाइन पैटर्न हैं जिनके बारे में मुझे जानकारी नहीं है?

किसी भी मदद के लिए धन्यवाद!


@DocBrown का उपयोग $this->context->addViolationकॉल के अंदर, अंदर किया जा रहा है if
IikeBreakfast

1
अंधा हो गया होगा, क्षमा करें।
डॉक ब्राउन

तो सभी :: स्टेटिक्स हैं?
इवान

हाँ, PHP में ::स्थिर विधियों के लिए है।
एंडी

@ ईवान हाँ, ::क्लास पर एक स्थिर विधि कहता है।
iLikeBreakfast

जवाबों:


11

कुछ पॉज़िबाइलाइट्स हैं, staticपीएचपी में कैसे तरीकों का मजाक उड़ाया जाए , मैंने जो सबसे अच्छा समाधान इस्तेमाल किया है, वह एस्पेक्टमॉक लाइब्रेरी है, जिसे संगीतकार के माध्यम से खींचा जा सकता है (स्थैतिक तरीकों का मजाक उड़ाने के लिए प्रलेखन से काफी समझ में आता है)।

हालाँकि, यह एक समस्या के लिए एक अंतिम मिनट फिक्स है जिसे अलग तरीके से तय किया जाना चाहिए।

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

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

class EmailAlertToSearchAdapterProxy
{
    public function adapt($value)
    {
        return EmailAlertToSearchAdapter::adapt($value);
    }
}

class SearcherFactoryProxy
{
    public function getSearchDirector(array $keywords)
    {
        return SearcherFactory::getSearchDirector($keywords);
    }
}

class ClassWithValidateMethod
{
    private $emailProxy;
    private $searcherProxy;

    public function __construct(
        EmailAlertToSearchAdapterProxy $emailProxy,
        SearcherFactoryProxy $searcherProxy
    )
    {
        $this->emailProxy = $emailProxy;
        $this->searcherProxy = $searcherProxy;
    }

    public function validate($value, Constraint $constraint)
    {
        $searchEntity = $this->emailProxy->adapt($value);

        $queryBuilder = $this->searcherProxy->getSearchDirector($searchEntity->getKeywords());
        $adapter = new SearchEntityToQueryAdapter($queryBuilder, $searchEntity);
        $query = $adapter->setupBuilder()->build();

        $totalCount = $this->advertType->count($query);

        if ($totalCount >= self::MAXIMUM_MATCHING_ADS) {
            $this->context->addViolation(
                $constraint->message
            );
        }
    }
}

यह पूर्ण है! प्रॉक्सी के बारे में भी नहीं सोचा था। धन्यवाद!
iLikeBreakfast

2
मेरा मानना ​​है कि माइकल फेदर ने अपनी पुस्तक "वर्किंग इफेक्टिवली विद लिगेसी कोड" में इसे "रैप स्टैटिक" तकनीक कहा है।
रबरडक

1
@ रुबरडैक मुझे पूरी तरह से यकीन नहीं है कि इसे ईमानदार कहा जाता है। यही कारण है कि मुझे इसे तब तक के लिए कहा जाता है, जब तक कि मैं इसका उपयोग करना याद रख सकता हूं, मिस्टर फेदर का नाम शायद बेहतर अनुकूल है, मैंने किताब नहीं पढ़ी है, हालांकि।
एंडी

1
कक्षा निश्चित रूप से एक "प्रॉक्सी" है। निर्भरता तोड़ने की तकनीक को "रैप स्टैटिक" IIRC कहा जाता है। मैंने किताब की बेहद सिफ़ारिश की है। यह आपके द्वारा उपलब्ध कराए गए रत्नों से भरा है।
रबरडक

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

4

सबसे पहले, मैं इसे अलग-अलग तरीकों से विभाजित करने का सुझाव दूंगा:

public function validate($value, Constraint $constraint)
{
    $totalCount = QueryTotal($value);
    ShowMessageWhenTotalExceedsMaximum($totalCount,$constraint);
}

private function QueryTotal($value)
{
    $searchEntity = EmailAlertToSearchAdapter::adapt($value);

    $queryBuilder = SearcherFactory::getSearchDirector($searchEntity->getKeywords());
    $adapter = new SearchEntityToQueryAdapter($queryBuilder, $searchEntity);
    $query = $adapter->setupBuilder()->build();

    return $this->advertType->count($query);
}

private function ShowMessageWhenTotalExceedsMaximum($totalCount,$constraint)
{
    if ($totalCount >= self::MAXIMUM_MATCHING_ADS) {
        $this->context->addViolation(
            $constraint->message
        );
    }
}

यह आपको उस स्थिति में छोड़ देता है जहां आप उन दो नए तरीकों को सार्वजनिक और इकाई परीक्षण QueryTotalऔर ShowMessageWhenTotalExceedsMaximumव्यक्तिगत रूप से बनाने पर विचार कर सकते हैं । यहाँ एक व्यवहार्य विकल्प वास्तव में इकाई परीक्षण के लिए नहीं है QueryTotal, क्योंकि आप अनिवार्य रूप से केवल इलास्टिक खोज का परीक्षण करेंगे। के लिए एक इकाई परीक्षण लिखना ShowMessageWhenTotalExceedsMaximumआसान होना चाहिए और बहुत अधिक समझ में आता है, क्योंकि यह वास्तव में आपके व्यापार तर्क का परीक्षण करेगा।

यदि, हालांकि, आप सीधे "मान्य" का परीक्षण करना पसंद करते हैं, तो क्वेरी फ़ंक्शन को "मान्य" (डिफ़ॉल्ट मान के साथ $this->QueryTotal) में एक पैरामीटर के रूप में पास करने पर विचार करें , इससे आप क्वेरी फ़ंक्शन का मजाक उड़ाएंगे। मुझे यकीन नहीं है कि मुझे PHP सिंटैक्स सही मिला है, इसलिए यदि मैंने नहीं किया है, तो कृपया इसे "छद्म कोड" के रूप में पढ़ें:

public function validate($value, Constraint $constraint, $queryFunc=$this->QueryTotal)
{
    $totalCount =  $queryFunc($value);
    ShowMessageWhenTotalExceedsMaximum($totalCount,$constraint);
}

मुझे विचार पसंद है, लेकिन मैं इस तरह के तरीकों से गुजरने के बजाय कोड को अधिक ऑब्जेक्ट-ओरिएंटेड रखना चाहता हूं।
iLikeBreakfast

@ लाइकब्रेकफास्ट वास्तव में यह दृष्टिकोण किसी भी चीज की परवाह किए बिना अच्छा है। एक तरीका जितना संभव हो उतना छोटा होना चाहिए और एक काम और एक चीज को अच्छी तरह से करना चाहिए (अंकल बॉब, क्लीन कोड )। यह पढ़ने में आसान, समझने में आसान और परीक्षण करने में आसान बनाता है।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.