Symfony2 में एक नियंत्रक का परीक्षण

मैं Symfony2 में नियंत्रकों के यूनिट परीक्षण के दृष्टिकोण के बारे में Symfony2 डेवलपर्स में से एक द्वारा कल के पोस्ट के अनुवाद पर आपका ध्यान आकर्षित करता हूं। सिम्फनी 2 डेवलपर्स के लिए विषय बहुत प्रासंगिक है। यह भी ध्यान देने योग्य है कि इस पोस्ट में सिम्फनी 2 में सेवा के रूप में एक नियंत्रक का उपयोग करने के बारे में देव-समूहों पर एक चर्चा के परिणाम का उल्लेख किया गया है।





MVC फ्रेमवर्क के साथ बहुत सारे अनुभव के साथ, एक चीज लगातार अनसुलझी बनी हुई है - नियंत्रकों का परीक्षण कैसे करें। मुझे लगता है कि इसका मुख्य कारण परीक्षण की गैर-स्पष्टता है, क्योंकि नियंत्रक ढांचे के "काले जादू" के तत्वों के प्रकार हैं। फ़ाइल सिस्टम में नियंत्रकों की नियुक्ति के बारे में कई समझौते हैं, उन्हें किन निर्भरताओं के बारे में पता होना चाहिए और नियंत्रक के पास क्या कठोर कनेक्शन होना चाहिए (देखें परत)।



ऐसी स्थिति नियंत्रकों का परीक्षण करने के लिए आसान तरीके नहीं देती है, जब तक कि आप एक नियंत्रक का चयन नहीं कर सकते हैं और परीक्षण बातचीत के लिए इसकी कुछ मुख्य निर्भरताएं हैं - आपको पूरे ढांचे को चलाने और कार्यात्मक परीक्षण चलाने की आवश्यकता है।



चूंकि यह प्रक्रिया काफी जटिल और जटिल है, लोग आमतौर पर नियंत्रकों के यूनिट परीक्षण का सहारा नहीं लेते हैं, कार्यात्मक परीक्षण अधिकतम हैं जो आप प्राप्त कर सकते हैं, लेकिन आमतौर पर परीक्षण बिल्कुल नहीं होता है।



Symfony2 पूरी तरह से चीजों को बदल रहा है।



प्रारंभ में, Symfony2 ढांचे में, केवल नियंत्रक लोडिंग समझौता है। नियंत्रक उदाहरण बहुत हल्का रहता है और इसके संचालन के लिए कुछ मूल वर्ग के विस्तार की आवश्यकता नहीं होती है। यदि आपके नियंत्रक कंटेनरवेयर इंटरफ़ेस को लागू करते हैं, तो आपको कंटेनरकेवेयर :: setContainer () विधि के माध्यम से कार्यान्वित एक डीआईसी (निर्भरता इंजेक्शन कंटेनर) मिलेगा, जिसका उपयोग आप डीआईसी में घोषित किसी भी सेवा का उपयोग करने के लिए कर सकते हैं।



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

<?php

$client = $ this ->createClient();



$client->request( 'GET' , '/index' );

$response = $client->getResponse();



$ this ->assertEquals(200, $response->getStatusCode());

$ this ->assertRegExp( '/<h1>My Cool Website<\/h1>/' , $response->getContent());




इस तथ्य के बावजूद कि यह विधि पढ़ने और समझने में आसान है, इसके नुकसान हैं: एक आदर्श दुनिया में, मैं अपने आवेदन में अन्य सेवाओं के साथ नियंत्रक की बातचीत का परीक्षण करना चाहूंगा, जैसे:

<?php



namespace Company\ApplicationBundle\Tests\Controller;

use Company\ApplicationBundle\Controller\IndexController;



class IndexControllerTest extends \PHPUnit_Framework_TestCase

{

//...

public function testIndexAction()

{

$templating = $ this ->getMock( 'Symfony\Bundle\FrameworkBundle\Templating\Engine' );

$templating->expects($ this ->once())

->method( 'render' )

->with( 'Application:Index:index' )

->will($ this ->returnValue( 'success' ))

;



$controller = new IndexController();

$controller->setTemplating($templating);



$ this ->assertEquals( 'success' , $controller->indexAction());

}

}





नोट: नियंत्रक अब आधार वर्ग के बिना POPO (सादा पुराना PHP ऑब्जेक्ट) है, जिसे इसे विस्तारित करना होगा। Symfony2 को काम करने के लिए कंट्रोलर क्लास के अलावा किसी और चीज की जरूरत नहीं है।



नोट: PHPUnit में नकली वस्तुओं के बारे में अधिक पढ़ें



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



ऊपर दिए गए उदाहरण से नियंत्रक के लिए सिम्फनी 2 के साथ सही ढंग से बातचीत करने के लिए और जैसा कि यह चाहिए, हमें निम्नलिखित की आवश्यकता है।



एक नियंत्रक वर्ग बनाएँ:

<?php



namespace Company\ApplicationBundle\Controller;

use Symfony\Bundle\FrameworkBundle\Templating\Engine;



class IndexController

{

/**

* @var Symfony\Bundle\FrameworkBundle\Templating\Engine

*/

private $templating;



/**

* @param Symfony\Bundle\FrameworkBundle\Templating\Engine $templating

*/

public function setTemplating(Engine $templating)

{

$ this ->templating = $templating;

}



/**

* @return Symfony\Component\HttpFoundation\Response

*/

public function indexAction()

{

return $ this ->templating->render( 'ApplicationBundle:Index:index' );

}

}






निम्नलिखित xml का उपयोग करके DIC कॉन्फ़िगरेशन बनाएँ:

<? xml version ="1.0" ? >



< container xmlns ="http://www.symfony-project.org/schema/dic/services"

xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation ="http://www.symfony-project.org/schema/dic/services www.symfony-project.org/schema/dic/services/services-1.0.xsd" >



< services >

< service id ="index_controller" class ="Company\ApplicationBundle\Controller\IndexController" >

< call method ="setTemplating" />

< argument type ="service" id ="templating" />

</ call >

</ service >

</ services >

</ container >






एक रूटिंग कॉन्फ़िगरेशन बनाएँ:

<? xml version ="1.0" encoding ="UTF-8" ? >



< routes xmlns ="http://www.symfony-project.org/schema/routing"

xmlns:xsi ="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation ="http://www.symfony-project.org/schema/routing www.symfony-project.org/schema/routing/routing-1.0.xsd" >



< route id ="index" pattern ="/index" >

< default key ="_controller" > index_controller:indexAction </ default >

</ route >

</ routes >






नोट: ऊपर के उदाहरण में, service_id: क्रिया का उपयोग सामान्य बंडल के बजाय किया गया था। बंडल: नियंत्रक: कार्रवाई (प्रत्यय 'एक्शन' के बिना)।



जब यह सब हो जाता है, तो हमें अपनी सेवाओं के बारे में Symfony2 को सूचित करना चाहिए। निर्भरता इंजेक्शन विस्तार नहीं बनाया जा सकता है और विन्यास फाइल के बिंदु बनाया जा करने के लिए, हम सीधे हमारी सेवाओं को पंजीकृत कर सकते हैं:



<?php



namespace Company\ApplicationBundle;



use Symfony\Component\HttpKernel\Bundle\Bundle;

use Symfony\Component\DependencyInjection\ContainerBuilder;

use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;



class ApplicationBundle extends Bundle {

public function registerExtensions(ContainerBuilder $container) {

parent::registerExtensions($container);



// register controllers

$loader = new XmlFileLoader($container);

$loader->load(__DIR__. '/Resources/config/controllers.xml' );

}

}






नोट: उक्त तकनीक मूल रूप से क्राइस वालस्मिथ द्वारा ओपनस्की में परियोजना के संयुक्त विकास के दौरान आवाज दी गई थी।



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



Company

| - ApplicationBundle

| | - Controller

| | | - IndexController.php

| | - Resources

| | | - config

| | | | - controller_routing.xml

| | | | - controllers.xml

| | | - views

| | | | - Index

| | | | | - index.php

| | - ApplicationBundle.php






इन चरणों को पूरा करने के बाद, आप URL टाइप करके ब्राउज़र में इसे आज़मा सकते हैं:

your_application/your_front_controller.php/index








All Articles