2013-02-10 47 views
23

मैं इकाई परीक्षण के बारे में सीखने गया था और मैं निम्नलिखित समस्या को हल करने का प्रयास किया:ZF2 इकाई परीक्षण प्रमाणीकरण

Zend\ServiceManager\ServiceManager::get was unable to fetch or create an instance for zfcUserAuthentication 

... में दिया ही जवाब का उपयोग कर:

Simple ZF2 Unit Tests for a controller using ZfcUser

तो मेरा सेटअप फ़ंक्शन वही दिखता है।

Zend\Mvc\Exception\InvalidPluginException: Plugin of type Mock_ZfcUserAuthentication_868bf824 is invalid; must implement Zend\Mvc\Controller\Plugin\PluginInterface 

यह कोड (मेरे कोड में एक ही तरह से अलग हो) के इस हिस्से में कारण होता है:

$this -> controller->getPluginManager() 
->setService('zfcUserAuthentication', $authMock); // Error refers to this line. 

$ authMock वस्तु जाहिरा तौर पर नहीं है दुर्भाग्य से, मैं त्रुटि संदेश मिलता है प्लगइनइंटरफेस को कार्यान्वित करना, जिसे मुझे setService में पास करने के लिए लागू करने की आवश्यकता है।

क्या $ authMock यूनिट परीक्षण में इसका उपयोग करने के लिए पास नहीं किया गया है? क्या मुझे एक अलग (इकाई-परीक्षण उन्मुख) सेट सेवा विधि का उपयोग करना चाहिए?

मुझे अपने आवेदन में लॉगिंग को संभालने का एक तरीका चाहिए, या मेरा यूनिट परीक्षण व्यर्थ है।

किसी भी सलाह के लिए धन्यवाद।

// Getting mock of authentication object, which is used as a plugin. 
$authMock = $this->getMock('ZfcUser\Controller\Plugin\ZfcUserAuthentication'); 

// Some expectations of the authentication service. 
$authMock -> expects($this->any()) 
    -> method('hasIdentity') 
    -> will($this->returnValue(true)); 

$authMock -> expects($this->any()) 
    -> method('getIdentity') 
    -> will($this->returnValue($ZfcUserMock)); 

// At this point, PluginManager disallows mock being assigned as plugin because 
// it will not implement plugin interface, as mentioned. 
$this -> controller->getPluginManager() 
->setService('zfcUserAuthentication', $authMock); 

हैं:

=== संपादित करें (2013/11/02) ===

मैं, स्पष्टीकरण के लिए इस हिस्से पर ध्यान केंद्रित करने के रूप में मुझे लगता है कि इस समस्या क्षेत्र है चाहता था नकली आवश्यक कार्यान्वयन को संभाल नहीं पाता है, मैं लॉगिन करने का नाटक कैसे करूँगा?

+0

क्या मैं इसे यूनिट-टेस्ट नियंत्रकों के लिए आवश्यक नहीं है क्योंकि यह मॉडल है? मुझे लगता है कि मैं अपने सभी प्रमाणीकरण कोड रखता हूं। – Shoreline

+0

मैंने हाल ही में कुछ समस्या के साथ ऐसा कुछ किया था। आपका पूरा टेस्टकेस वर्ग कैसा दिखता है? आपका टेस्ट बूटस्ट्रैप कैसा दिखता है? और अंत में आप जिस क्रिया का परीक्षण करने की कोशिश कर रहे हैं। – Ruben

+0

क्या यूनिट परीक्षण करते समय आप एक विशेष अनुप्रयोग कॉन्फ़िगरेशन का उपयोग करते हैं? यह उस मामले में संभव है कि zfcUser मॉड्यूल परीक्षण वातावरण में लोड नहीं किया गया है। – SmasherHell

उत्तर

3

आपको नाम-अंतर या आपके ऑटोलोडर के साथ कोई समस्या है।

जब आप अपना मॉक बना रहे हैं, तो ZfcUser\Controller\Plugin\ZfcUserAuthentication की कक्षा परिभाषा नहीं मिल रही है। तो PHPUnit एक नकली बनाता है जो केवल इस परीक्षा को आपके परीक्षण के लिए बढ़ाता है। यदि कक्षा उपलब्ध थी तो PHPUnit वास्तविक वर्ग का उपयोग अपने मॉक बनाने के दौरान करने के लिए करेगा, जो तब माता-पिता वर्ग/इंटरफेस का उपयोग करेगा।

आप इस तर्क यहाँ देख सकते हैं: https://github.com/sebastianbergmann/phpunit-mock-objects/blob/master/PHPUnit/Framework/MockObject/Generator.php

if (!class_exists($mockClassName['fullClassName'], $callAutoload) && 
     !interface_exists($mockClassName['fullClassName'], $callAutoload)) { 
     $prologue = 'class ' . $mockClassName['originalClassName'] . "\n{\n}\n\n"; 

     if (!empty($mockClassName['namespaceName'])) { 
      $prologue = 'namespace ' . $mockClassName['namespaceName'] . 
         " {\n\n" . $prologue . "}\n\n" . 
         "namespace {\n\n"; 

      $epilogue = "\n\n}"; 
     } 

     $cloneTemplate = new Text_Template(
      $templateDir . 'mocked_clone.tpl' 
     ); 

तो अगर कोई वर्ग या इंटरफेस है, PHPUnit वास्तव में एक ही पैदा करेगा ताकि नकली मूल वर्ग के नाम के प्रकार हिंट को पूरा करेगा। हालांकि, किसी भी अभिभावक वर्ग या इंटरफेस को शामिल नहीं किया जाएगा क्योंकि PHPUnit उनसे अवगत नहीं है।

यह आपके परीक्षण में उचित नामस्थान या आपके ऑटोलोडर में कोई समस्या नहीं होने के कारण होगा। वास्तव में पूरी टेस्ट फ़ाइल को देखे बिना बताना मुश्किल है।


वैकल्पिक रूप से नहीं बल्कि ZfcUser\Controller\Plugin\ZfcUserAuthentication मजाक से, आप अपने परीक्षण में Zend\Mvc\Controller\Plugin\PluginInterface नकली और प्लगइन प्रबंधक में पारित है कि हो सकता है। यद्यपि यदि आप अपने कोड में प्लगइन के लिए टाइप-हिंटिंग कर रहे हैं, तो आपका परीक्षण अभी भी काम नहीं करेगा।

//Mock the plugin interface for checking authorization 
$authMock = $this->getMock('Zend\Mvc\Controller\Plugin\PluginInterface'); 

// Some expectations of the authentication service. 
$authMock -> expects($this->any()) 
    -> method('hasIdentity') 
    -> will($this->returnValue(true)); 

$authMock -> expects($this->any()) 
    -> method('getIdentity') 
    -> will($this->returnValue($ZfcUserMock)); 

$this -> controller->getPluginManager() 
->setService('zfcUserAuthentication', $authMock); 
0

मैंने अभी FlashMessenger प्लगइन के लिए एक उदाहरण बनाया है। ControllerPlugin को ओवरराइड करने के लिए आपको केवल ControllerPluginManager का उपयोग करना चाहिए। सुनिश्चित करें कि आपका एप्लिकेशन बूटस्ट्रैप सेट एप्प्लिकेशन कॉन्फिग() पर कॉल करता है;

<?php 
namespace SimpleTest\Controller; 

use Zend\Test\PHPUnit\Controller\AbstractHttpControllerTestCase; 

class SimpleControllerTest extends AbstractHttpControllerTestCase { 

    public function testControllerWillAddErrorMessageToFlashMessenger() 
    { 
     $flashMessengerMock = $this->getMockBuilder('\Zend\Mvc\Controller\Plugin\FlashMessenger', array('addErrorMessage'))->getMock(); 
     $flashMessengerMock->expects($this->once()) 
      ->method('addErrorMessage') 
      ->will($this->returnValue(array())); 


     $serviceManager = $this->getApplicationServiceLocator(); 
     $serviceManager->setAllowOverride(true); 
     $serviceManager->get('ControllerPluginManager')->setService('flashMessenger', $flashMessengerMock); 

     $this->dispatch('/error/message'); 

    } 
}?>