2012-09-26 16 views
16

मैं यूनिट परीक्षण और PHPUnit के लिए नया हूं।PHPUnit में दिए गए इंटरफ़ेस को लागू करने वाले नकली ऑब्जेक्ट पर अपरिभाषित विधि?

मुझे एक नकली की ज़रूरत है, जिस पर मेरा पूरा नियंत्रण है, ConfigurationInterface इंटरफेस को कार्यान्वित करना। टेस्ट विषय ReportEventParamConverter ऑब्जेक्ट और परीक्षण को मेरी ऑब्जेक्ट और इंटरफ़ेस के बीच बातचीत की जांच करनी चाहिए।

ReportEventParamConverter वस्तु (यहाँ सरलीकृत):

class ReportEventParamConverter implements ParamConverterInterface 
{ 
    /** 
    * @param Request $request 
    * @param ConfigurationInterface $configuration 
    */ 
    function apply(Request $request, ConfigurationInterface $configuration) 
    { 
     $request->attributes->set($configuration->getName(), $reportEvent); 
    } 

    /** 
    * @param ConfigurationInterface $configuration 
    * @return bool 
    */ 
    function supports(ConfigurationInterface $configuration) 
    { 
     return 'My\Namespaced\Class' === $configuration->getClass(); 
    } 
} 

और इस तरह मैं इंटरफ़ेस उपहास करने के लिए कोशिश कर रहा हूँ है:

$cls = 'Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface'; 
$mock = $this->getMock($mockCls); 

मैं दो के लिए लौट आए मूल्यों अनुकरण करने की जरूरत है विधियां: getClass() और getName()। उदाहरण के लिए:

$mock->expects($this->any()) 
    ->method('getClass') 
    ->will($this->returnValue('Some\Other\Class')) 
; 

जब मैं एक नया ReportEventParamConverter और परीक्षण supports() विधि बनाने के लिए, मैं निम्नलिखित PHPUnit त्रुटि मिलती है:

Fatal error: Call to undefined method Mock_ConfigurationInterface_21e9dccf::getClass().

$converter = new ReportEventParamConverter(); 
$this->assertFalse($converter->supports($mock)); 
+0

क्या 'पैराम कनवर्टरइंटरफेस' में 'getClass()' विधि है? – hakre

+0

@ हाकरा क्या मायने रखता है? – gremo

+0

कृपया अपने प्रश्न में अधिक जानकारी जोड़ने के लिए प्रश्न का उत्तर दें। इससे कोई फर्क नहीं पड़ता। इसके अलावा, यह मेरी पहली धारणा होगी कि नकली के पास ऐसा कार्य क्यों नहीं है। तो कुछ बुनियादी डीबगिंग। – hakre

उत्तर

18

यह क्योंकि वहाँ में "getClass" विधि का कोई घोषणा है है ConfigurationInterface। इस इंटरफेस में एकमात्र घोषणा विधि "getAliasName" है।

आपको बस आप नकली क्या तरीकों stubing किया जाएगा बताने के लिए है: नहीं "getClass" घोषणा है

$cls = 'Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface'; 
$mock = $this->getMock($mockCls, array('getClass', 'getAliasName')); 

सूचना है कि वहाँ है, लेकिन आप ठूंठ कर सकते हैं/नकली गैर मौजूदा पद्धति के रूप में अच्छी तरह से। वजह आप इसे नकली कर सकते हैं:

$mock->expects($this->any()) 
    ->method('getClass') 
    ->will($this->returnValue('Some\Other\Class')); 

लेकिन इसके अलावा में आप "getAliasName" विधि उपहास करने के लिए और साथ ही लंबे समय से यह इंटरफेस की विधि या सार एक है और यह "कार्यान्वित" हो गया है के रूप में की जरूरत है। उदाहरण:

$mock->expects($this->any()) 
    ->method('getAliasName') 
    ->will($this->returnValue('SomeValue')); 
+0

तो यदि विधियां मौजूद नहीं हैं मूल वर्ग में 'getMock()' कॉल में घोषित किया जाना चाहिए? यदि विधि मौजूद है तो यह आवश्यक नहीं है? – gremo

+3

आपको हमेशा यह कहना चाहिए कि आप किस विधि को स्टब/मॉक करने जा रहे हैं। यदि आप इसे निर्दिष्ट नहीं करते हैं, तो नकली मान लीजिए कि आप कक्षा से सभी विधियों को दबाएंगे (उदाहरण के लिए। यदि आप केवल एक विधि विधि ए, $ mock = $ this-> getMock ('class', array ('methodA')) निर्दिष्ट करते हैं, तो नकली मान लीजिए कि आप केवल नकली हैं methodA, और जब आप किसी अन्य विधि को कॉल करते हैं: $ mock-> methodB(), तो "कक्षा" से "असली" विधि निष्पादित की जाती है) – Cyprian

+0

धन्यवाद! अब काम करता है। – gremo

12

साइप्रियन के उत्तर ने मेरी मदद की, लेकिन इसके बारे में जागरूक होने के लिए एक गोचा है। आप उन कक्षाओं का नकल कर सकते हैं जो मौजूद नहीं हैं, और PHPUnit शिकायत नहीं करेगा। तो तुम कर सकते हो

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

इसका मतलब यह है कि अगर ConfigurationInterface रनटाइम के दौरान उस बिंदु पर मौजूद नहीं है, तो आप अभी भी एक संदेश की तरह

Fatal error: Call to undefined method Mock_ConfigurationInterface_21e9dccf::getClass().

मिलेगा आप विधि वास्तव में आश्वस्त हैं कि कक्षा में मौजूद है, तो संभावित समस्या यह है कि कक्षा स्वयं मौजूद नहीं है (क्योंकि आपको इसकी आवश्यकता नहीं है, या आपने इसे गलत वर्तनी, आदि)।


ओपी एक इंटरफ़ेस उपयोग कर रहा है।ध्यान दें कि आप विधि की सूची निर्दिष्ट करने ओवरराइड करने के लिए बिना getMock कॉल करना होगा, या अगर आप ऐसा करेंगे, तो आप या तो array() से गुजरना होगा, या सभी विधि के नाम से पारित, या आप निम्नलिखित की तरह एक त्रुटि मिल जाएगा:

PHP Fatal error: Class Mock_HttpRequest_a7aa9ffd contains 4 abstract methods and must therefore be declared abstract or implement the remaining methods (HttpRequest::setOption, HttpRequest::execute, HttpRequest::getInfo, ...)

+2

इसका उल्लेख करने के लिए धन्यवाद, यह वास्तव में एक लापता वर्ग था मुझे समस्याएं पैदा कर रही हैं। – ChiperSoft

+0

धन्यवाद। एच एक ही समस्या का विज्ञापन करें। – Mantas

+0

मैंने बाहरी लाइब्रेरी का मज़ाक उड़ाते हुए इसका अनुभव किया, जिसे परीक्षण के तहत कक्षा में 'आवश्यकता' थी, लेकिन ऑटोलोडर के अनुरूप नहीं था। –

1

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

$methods = array_map(function (\ReflectionMethod $m) { return $m->getName();}, (new \ReflectionClass($interface))->getMethods()); 
$methods[] = $missing_method; 
$mock = $this->getMock($interface, $methods); 

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^