2012-10-03 20 views
5

में यूनिट परीक्षण के दौरान एक अलग ईमेल कॉन्फ़िगरेशन का उपयोग करें मैं अपने नियंत्रकों में से एक की कार्रवाई में केकेईमेल क्लास का उपयोग कर एक ईमेल भेज रहा हूं। मेरे पास इस नियंत्रक के लिए एक यूनिट परीक्षण है जो ईमेल कोड जोड़ने से पहले ठीक काम कर रहा था।केकेपीएचपी

SocketException: Could not send email.

इस तथ्य को मैं अपने स्थानीय मशीन बंद ईमेल भेजने के लिए किसी भी तरह की जरूरत नहीं है कि करने के लिए नीचे है: ईमेल जोड़ने के बाद मैं इस त्रुटि मिलती है।

इसलिए मैंने सोचा कि शायद एक अच्छा विचार है कि कॉन्फ़िगर/email.php में ईमेल कॉन्फिग क्लास के अंदर दो अलग-अलग कॉन्फ़िगरेशन विकल्प होंगे (डेटाबेस कॉन्फ़िगरेशन फ़ाइल कैसे काम करता है)। मेल परिवहन का उपयोग करके डिफ़ॉल्ट, और डीबग परिवहन का उपयोग कर एक परीक्षण। इसके साथ समस्या यह है कि, डेटाबेस कॉन्फ़िगरेशन के विपरीत, केक स्वचालित रूप से परीक्षण के दौरान दोनों के बीच स्विच नहीं करता है।

एकमात्र चीज जिसे मैंने सोचा है, ईमेलकॉन्फ क्लास में एक कन्स्ट्रक्टर जोड़ना है और परीक्षण करना है कि हम यूनिट परीक्षण कर रहे हैं, लेकिन मुझे यकीन नहीं है कि चेक क्या होना चाहिए।

इस की तर्ज पर कुछ:

class EmailConfig { 

    public $default = array(
     'transport' => 'Mail' 
    ); 

    public $test = array(
     'transport' => 'Debug' 
    ); 

    public function __construct() { 
     if ($isUnitTesting) { 
      $this->default = $this->test; 
     } 
    } 

} 

मेरे रास्ते ऊपर सुझाए गए हैं एक अच्छा विचार हो सकता है? यदि नहीं, तो इकाई परीक्षण के दौरान ईमेल के लिए मैं अन्य तरीकों का उपयोग कैसे कर सकता हूं?


अपडेट - 4/10/2012

मुझे लगता है कि मैं गलत तरीके से इस बारे में जा रहा था। this answer पर देखकर ऐसा लगता है कि $default कॉन्फ़िगरेशन डिफ़ॉल्ट रूप से लोड नहीं होता है, आपको इसे CakeEmail::config() विधि पर कॉल करके या इसे कन्स्ट्रक्टर में देकर निर्दिष्ट करना होगा। इसलिए मैं यह मेरे पत्ते अब दो विकल्प लगता है: (? किसी भी तरह)

  1. नियंत्रक की जांच में अगर हम इकाई परीक्षण कर रहे हैं और फिर 'परीक्षण' config का उपयोग करें।
  2. ईमेल भेजने में सक्षम होने के लिए मेरे कंप्यूटर को सेट करें।

मैं पहले ऐसा करना चाहता हूं लेकिन यह सुनिश्चित नहीं करता कि यह जांच के साथ नियंत्रक कार्रवाई को फुलाए बिना कैसे किया जा सकता है यदि हम यूनिट परीक्षण कर रहे हैं, तो ऐसा करना गलत लगता है।

+0

बस अपने परीक्षण मामले पर 'सेटअप' में कॉन्फ़िगरेशन सेट अप करें। एफवाईआई, केक एक 'डीबगट्रांसपोर्ट' के साथ आता है जिसे आप अपनी कॉन्फ़िगरेशन सेटिंग्स में उपयोग कर सकते हैं जो वास्तव में भेजने के अलावा सब कुछ करेगा, और आपके परीक्षणों में उपयोग करने के लिए हेडर और संदेश लौटाएगा। सुपर सहायक :) – jeremyharris

+0

आपकी समस्याएं परीक्षण से बड़ी हो सकती हैं। वास्तविक जीवन में ईमेल नियमित रूप से विफल हो जाते हैं; सुनिश्चित करें कि उसके लिए कोड खाते हैं। मैं 1) सुनिश्चित करता हूं कि परीक्षण सफल और असफल ईमेल दोनों के लिए मौजूद हैं और 2) नकली केकईमेल ऑब्जेक्ट का उपयोग करने का प्रयास करें। सुनिश्चित नहीं है कि आप # 2 करने के बारे में कैसे जाएंगे; अन्यथा मैं जवाब दूंगा। –

+0

@ जेरेमीहरिस मैं पहले ही डीबगट्रांसपोर्ट के बारे में जानता था, वास्तव में मैं उन तरीकों को देख रहा था जिनका उपयोग मेलट्रांसपोर्ट के बजाय किया जा सकता था। क्या आप सेटअप में कॉन्फ़िगरेशन को सेट अप करने के तरीके पर विस्तार करने में सक्षम होंगे, मैं अपने सिर को काफी काम करने में सक्षम नहीं था कि यह कैसे काम कर सकता है। – Josh

उत्तर

4

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

App::uses('CakeEmail', 'Network/Email'); 
App::uses('AppController', 'Controller'); 

class UsersController extends AppController { 

    public function register() { 
    //registration logic 
    $email = new CakeEmail(); 
    $email->from(array('[email protected]' => 'Site')); 
    $email->to('[email protected]'); 
    $email->subject('Registered'); 
    $email->send('Thanks for registering!'); 
    } 

} 

यह हानिरहित लग रहा है, लेकिन आप CakeEmail नकली नहीं कर सकते क्योंकि यह dependency injection है, जो आवश्यक है जब परीक्षण के लिए अनुमति नहीं है। इसके बजाए, CakeEmail वर्ग को इस तरह से तत्काल स्थापित किया जाना चाहिए जो हमें बाद में इसे बदलने की अनुमति देता है। उदाहरण के लिए:

App::uses('CakeEmail', 'Network/Email'); 
App::uses('AppController', 'Controller'); 

class UsersController extends AppController { 

    public function register() { 
    //registration logic 
    $email = $this->_getEmailer(); 
    $email->from(array('[email protected]' => 'Site')); 
    $email->to('[email protected]'); 
    $email->subject('Registered'); 
    $email->send('Thanks for registering!'); 
    } 

    public function _getEmailer() { 
    return new CakeEmail(); 
    } 

} 

क्योंकि हमने थोड़ा सहायक फ़ंक्शन जोड़ा है, अब हम इसका परीक्षण कर सकते हैं (सहायक फ़ंक्शन का मज़ाक उड़ाकर)।

App::uses('CakeEmail', 'Network/Email'); 
App::uses('UsersController', 'Controller'); 

class UsersControllerTest extends ControllerTestCase { 

    public function testRegister() { 
    $controller = $this->generate('Users', array(
     'methods' => array(
     '_getEmailer' 
    ) 
    )); 
    $emailer = new CakeEmail(); 
    $emailer->transport('Debug'); 
    $controller 
     ->expects($this->any()) 
     ->method('_getEmailer') 
     ->will($this->returnValue($emailer)); 
    } 

} 

यह परीक्षण हमारे नियंत्रक के लिए एक नकली वस्तु बनाता है और यह बताता है कि जब _getEmailer विधि कहा जाता है हमारे नव निर्मित $emailer वस्तु वापस जाने के लिए। चूंकि $emailer ने परिवहन को 'डीबग' पर सेट कर दिया है, यह परीक्षण के लिए सुरक्षित है।

बेशक, अब से हम निर्णय ले रहे हैं कि विधि क्या ईमेल ऑब्जेक्ट लौटाता है, CakeEmail ऑब्जेक्ट का मज़ाक उड़ाता है और कुछ रिटर्न की अपेक्षा तुच्छ हो जाती है।

+0

_getEmailer फ़ंक्शन को कई नियंत्रकों में उपयोग करने के लिए AppController में स्थानांतरित किया जा सकता है और अभी भी इस तरह से काम कर सकता है? –

+0

@ BoštjanPišler हां, जब तक कि बच्चे के नियंत्रक '_getEmailer()' को ऐसे तरीके से ओवरराइट नहीं करते हैं जो इसे बदलना चाहिए। (* नोट: यह एक बहुत पुराना उत्तर है और केवल केक 2.x पर लागू होता है *) – jeremyharris

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