2009-07-22 14 views
20

मैं सरलतम से PHPUnit तक परीक्षणों का एक गुच्छा माइग्रेट करने की कोशिश कर रहा हूं और मैं सोच रहा था कि क्या सरलटेस्ट के partial mocks के बराबर है।PHPUnit में SimpleTest "आंशिक mocks" के समतुल्य?

अद्यतन: मैं डॉक्स जो पता चलता है कि यह सुविधा उपलब्ध है में कुछ भी नहीं कर पा रहे हैं, लेकिन यह मेरे लिए हुआ है कि मैं सिर्फ एक उपवर्ग इस्तेमाल कर सकते हैं। क्या यह एक अच्छा या बुरा विचार है?

class StuffDoer { 
    protected function doesLongRunningThing() { 
     sleep(10); 
     return "stuff"; 
    } 
    public function doStuff() { 
     return $this->doesLongRunningThing(); 
    } 
} 
class StuffDoerTest { 
    protected function doesLongRunningThing() { 
     return "test stuff"; 
    } 
} 
class StuffDoerTestCase extends PHPUnit_Framework_TestCase { 
    public function testStuffDoer() { 
     $sd = new StuffDoerTest(); 
     $result = $sd->doStuff(); 
     $this->assertEquals($result, "test stuff"); 
    } 
} 
+0

उपclass विचार के लिए धन्यवाद! – Kyslik

उत्तर

40

लिंक किए गए पृष्ठ पढ़ने से, एक SimpleTest आंशिक नकली एक नकली जहां केवल तरीकों के कुछ अधिरोहित कर रहे हैं लगता है। यदि यह सही है, तो कार्यक्षमता को सामान्य PHPUnit नकली द्वारा नियंत्रित किया जाता है।

एक PHPUnit_Framework_TestCase के अंदर, आप

$mock = $this->getMock('Class_To_Mock'); 

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

$mock = $this->getMock('Class_To_Mock', array('insert', 'update')); 

उनकी वापसी मान निर्दिष्ट होने के लिए तैयार हटाया insert और update काम करता है, के साथ Class_To_Mock का एक नकली उदाहरण पैदा करेगा।

यह जानकारी phpunit docs में है।

नोट, this answer तारीख कोड उदाहरण के लिए ऊपर और अधिक पता चलता है, शुरू करने 5.4

1

मैं PHPUnit परीक्षण के अंतर्गत प्रणाली के लिए आंशिक mocks का समर्थन करता है नहीं लगता कि PHPUnit संस्करणों के लिए। यदि आप विधियों को अलग करने की कोशिश कर रहे हैं तो मुझे यकीन है कि आपका कार्यान्वयन कार्य करता है - मैंने भी ऐसा किया है।

हालांकि, मैं यह कर रहा से बचने के लिए, कारणों की एक जोड़ी के लिए प्रयास करें।

सबसे पहले, यह जोड़ों के अपने बहुत वर्ग की आंतरिक कार्यान्वयन के लिए कसकर परीक्षण। क्या आप वास्तव में परवाह करते हैं कि doesLongRunningThing नामक एक विधि को बुलाया गया था, या यह अधिक महत्वपूर्ण है कि "LongRunningThing" किया गया हो?

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

मेरा मानना ​​है कि समाधान (http://en.wikipedia.org/wiki/Dependency_injection) पर सेवाओं अपने SUT निर्भर करता है इंजेक्षन करने के लिए है। यह DoesLongRunningThing कार्यान्वयन को और अधिक टेस्टेबल बनाता है।

इंटरफेस में कूद के बिना, यहाँ मैं क्या कर सकता है:

class DoesLongRunningThing { 
    public function execute() { 
     sleep(10); 
     return "stuff"; 
    } 
} 

class StuffDoer { 
    protected $doesLongRunningThing; 

    public function setLongRunningThinger(DoesLongRunningThing $obj) { 
     $this->doesLongRunningThing = $obj; 
    } 

    public function doStuff() { 
     return $this->doesLongRunningThing->execute(); 
    } 
} 

अब यह नकली करना आसान है:

class StuffDoerTestCase extends PHPUnit_Framework_TestCase { 
    public function testStuffDoer() { 
     $dlrtMock = $this->getMock('DoesLongRunningThing'); 
     $dlrtMock->expects($this->any())->will($this->returnValue("test stuff")); 

     $sd = new StuffDoer(); 
     $sd->setLongRunningThinger($dlrtMock); 
     $result = $sd->doStuff(); 
     $this->assertEquals($result, "test stuff"); 
    } 
} 
+0

मुझे लगता है कि PHPUnit सिर्फ एक उपकरण है, और यह परीक्षण के तहत सिस्टम की परवाह नहीं करता है (यह एक उपकरण उपयोगकर्ता का सौदा है)। ब्रेंटन के उत्तर के अनुसार, PHPUnit _supports_ "आंशिक मोक्स"। पहली वाक्य के बाद आपका जवाब सही है (इसके लिए +1)। –

8

PHPUnit_Framework_TestCase::getMock is deprecated since phpunit 5.4। हम इसके बजाय setMethods का उपयोग कर सकते हैं।

setMethods (सरणी $ विधि) तरीकों कि एक विन्यास परीक्षण डबल के साथ प्रतिस्थापित किया जा रहे हैं निर्दिष्ट करने के लिए नकली बिल्डर वस्तु पर कहा जा सकता है। अन्य तरीकों का व्यवहार नहीं बदला गया है। अगर आप setMethods (शून्य) कहते हैं, तो कोई विधि प्रतिस्थापित नहीं की जाएगी।

https://phpunit.de/manual/current/en/test-doubles.html

$observer = $this->getMockBuilder(Observer::class) 
       ->setMethods(['update']) 
       ->getMock(); 

ध्यान दें कि ऊपर getMockPHPUnit_Framework_MockObject_MockBuilder::getMock है। (phpunit5.6)