2012-02-17 13 views
11

मुझे गुणों के डिफ़ॉल्ट सेट के साथ एक नकली वस्तु बनाने की आवश्यकता है ताकि इसे तत्काल पर कोडबेस में एल्सवेयर का उपयोग किया जा सके।डिफ़ॉल्ट गुणों के साथ एक नकली वस्तु बनाना

$mock = $this->getMock('MyClass', array(), array(), 'MyClass_Mock'); 
$mock->prop = 'foobar'; 

$myclassMock = new get_class($mock); 
var_dump($myclassMock->prop); // NULL 
// How can I make this dump 'foobar' ? 

मैं रूपरेखा है कि निर्धारित करता है स्थित है, और इन वर्गों को दर्शाता है तो मज़ाक उड़ाया वस्तु इंजेक्शन लगाने के परीक्षण का उद्देश्य विफल हो जाएगा का हिस्सा परीक्षण कर रहा हूँ।

मैं किसी भी तरीकों उपहास करने के लिए .. बस गतिशील इसलिए की तरह एक मज़ाक उड़ाया वर्ग बनाने की आवश्यकता नहीं है:

class MyClass_Mock extends MyClass { 
    public $prop = 'foobar'; 
} 

संपादित करें: सरलीकृत उदाहरण

+0

बस स्पष्टता के लिए, आप मौजूदा वर्ग का नकल करना चाहते हैं, और वास्तव में उस वर्ग के डिफ़ॉल्ट गुणों को अपने वर्ग को डिफ़ॉल्ट रूप से मजाक कर रहे हैं? – Leigh

+0

@ लेघ राइट, कक्षा ढांचे में गहराई से तत्काल हो जाएगी। जिस कक्षा में मैं मजाक कर रहा हूं वह एक अमूर्त मॉडल है, और मैं इसे कुछ '$ फ़ील्ड' देना चाहता हूं, इसलिए यह वास्तविक मॉडल की तरह व्यवहार करेगा। मुझे पता है कि PHPUnit कोड को स्ट्रिंग में लिखकर और इसे विकसित करके मोजे बनाता है()। मुझे नहीं पता कि उस प्रक्रिया में संपत्ति घोषणाओं को कैसे शामिल किया जाए। –

उत्तर

4

आप प्रतिबिंब का उपयोग कर के बारे में कैसा लगता है?

$r = new ReflectionClass('MyClass'); 

$props = $r->getDefaultProperties(); 

$mock = new stdClass; 

foreach ($props as $prop => $value) { 
    $mock->$prop = $value; 
} 

मैंने केवल मूल आत्मनिरीक्षण के लिए प्रतिबिंब का उपयोग नहीं किया है। मुझे यकीन नहीं है कि आप इसका उपयोग कर दृश्यता इत्यादि की पूरी तरह नकल करने में सक्षम होंगे, लेकिन मुझे नहीं लगता कि क्यों आप स्ट्रिंग में लिखने के मार्ग को जारी रखते हैं और eval आईएनजी नहीं करते हैं।

संपादित करें:

जिज्ञासा से बाहर प्रतिबिंब कार्यों के माध्यम से स्कैन किए गए, यह पूरी तरह से डमी तरीकों के साथ वर्ग की नकल करने के लिए पूरी तरह से संभव है पूर्ण दृश्यता की कमी, स्थिरांक, और स्थिर तत्वों को लागू जहां उपयुक्त हो अगर आप गतिशील रूप से निर्माण एक स्ट्रिंग में वर्ग और eval यह।

हालांकि ऐसा लगता है कि यह एक पूरी मिशन वास्तव में पूरी तरह से हर संभावना का समर्थन करने के जब यह डेटा प्रकार सही हो रही करने के लिए नीचे आता है (उदाहरण के लिए एक सरणी से एक सरणी निर्माता के पुनर्निर्माण के लिए कोड की आवश्यकता होगी)

बेस्ट ऑफ लक यदि आप इस मार्ग नीचे जाना, यह अधिक मस्तिष्क शक्ति की आवश्यकता है की तुलना में मैं अभी :) अतिरिक्त करने को तैयार हूँ

यहाँ कोड का एक छोटा सा है, तो आप स्थिरांक के साथ एक ही बात कर सकते हैं, और एक ही तरीके से खाली तरीके बनाएँ।

class Test 
{ 
    private static $privates = 'priv'; 
    protected $protected = 'prot'; 
    public $public = 'pub'; 
} 

$r = new ReflectionClass('Test'); 

$props = $r->getDefaultProperties(); 

$mock = 'class MockTest {'; 

foreach ($props as $prop => $value) { 
    $rProp = $r->getProperty($prop); 


    if ($rProp->isPrivate()) { 
     $mock .= 'private '; 
    } 
    elseif ($rProp->isProtected()) { 
     $mock .= 'protected '; 
    } 
    elseif ($rProp->isPublic()) { 
     $mock .= 'public '; 
    } 

    if ($rProp->isStatic()) { 
     $mock .= 'static '; 
    } 

    $mock .= "$$prop = "; 

    switch (gettype($value)) { 
     case "boolean": 
     case "integer": 
     case "double": 
      $mock .= $value; 
      break; 
     case "string": 
      $mock .= "'$value'"; 
      break; 
/* 
"array" 
"object" 
"resource" 
*/ 
    case "NULL": 
      $mock .= 'null'; 
      break; 
    } 

    $mock .= ';'; 
} 

$mock .= '}'; 

eval($mock); 

var_dump(new MockTest); 
+2

अगर मैं कर सकता तो मैं आपको दो बार ऊपर उठाऊंगा। प्रयास में शामिल होने के लिए धन्यवाद .. मैंने अब तक प्रतिबिंब मार्ग की कोशिश नहीं की है लेकिन यह दिलचस्प लगता है। मैं आपके कुछ सुझावों को आज़मा दूंगा और देख सकता हूं कि यह कैसे जाता है :) –

3

मुझे यकीन है कि तुम भी जरूरत परीक्षण प्रयोजनों के लिए यह करने के लिए नहीं कर रहा हूँ।

आमतौर पर जब मॉडल एक्सेस शामिल होता है तो परीक्षण मॉडल में आप वास्तविक मॉडल का मज़ाक उड़ाते हुए फिक्स्चर का उपयोग करते हैं क्योंकि मॉडल "गूंगा" डेटा संरचनाएं हैं जो किसी भी क्षमताओं का खुलासा नहीं करती हैं जिन्हें मजाक करने की आवश्यकता होती है।

आपका उदाहरण यह कहता है: यदि आपको व्यवहार (विधियों) का नकल करने की आवश्यकता नहीं है, तो आपको नकली ऑब्जेक्ट की आवश्यकता नहीं है। इसके बजाय आपको एक डेटा स्थिरता की आवश्यकता है कि मॉडल इसके डेटा स्रोत के रूप में उपयोग करता है। यह विशेष रूप से सच है, जैसा कि आप कहते हैं, "निर्भरता इंजेक्शन एक विकल्प नहीं है"

बेशक, यदि आप तय करते हैं कि आप मॉडल को नकली बनाना चाहते हैं, तो मैं @ लेघ के प्रतिबिंब समाधान का सुझाव दूंगा।

मैं सिर्फ कल डेटाबेस परीक्षण के बारे में एक सवाल का जवाब है कि आप और अधिक विस्तार के लिए थोड़ा बाहर की जाँच हो सकता है: PHPUnit: How to test database interactions on remote Postgres server?

+0

अच्छे अंक। मुझे लगता है कि आप कह सकते हैं कि मैं एक गतिशील स्थिरता बनाने की कोशिश कर रहा हूं। मैं गलत मॉडल बनाकर अंतर्निहित मॉडल ढांचे का परीक्षण करने की कोशिश कर रहा हूं। हमारे मॉडल संरक्षित गुणों के माध्यम से लगभग पूरी तरह से कॉन्फ़िगर किए गए हैं, इसलिए मैं केवल 'संरक्षित $ _fields = array (' firstname, 'lastname') करके उपयोगकर्ता मॉडल बना सकता हूं; '। मेरा लक्ष्य है कि अंतर्निहित ढांचे का परीक्षण करने के लिए गतिशील रूप से फर्जी मॉडल बनाकर किसी भी स्थिति को फिर से बनाने की क्षमता हो। मैंने डेटा-गेटवे और शेष ढांचे को पहले से ही मजाक कर दिया है .. मुझे केवल डिफ़ॉल्ट प्रोप –

+0

आह के साथ गतिशील कक्षाएं बनाने की क्षमता की आवश्यकता है। उस मामले में, हर तरह से, उन मॉडलों का मज़ाक उड़ाओ। आम तौर पर इस तरह के कुछ के साथ मैं मॉडल को "संग्रह" ऑब्जेक्ट पर आधारित करता हूं जो सभी गुणों को एक संरक्षित सरणी में संग्रहीत करता है और संपत्ति को पढ़ने/लिखने के लिए जादू '__get' और '__set' के साथ' ArrayAccess' लागू करता है। यदि आपने ऐसा किया है तो आप एक कुंजी/मूल्य सरणी से एक स्ट्रोक में मॉडल को पॉप्युलेट करने के लिए अपने 'मॉडल :: लोड' विधि में फेंक सकते हैं। इस तरह की 'लोड' विधि ऑब्जेक्ट को किसी भी जानकारी के साथ पॉप्युलेट कर देगी जो आप बहुत सरल चाहते थे। इसके अलावा, यदि आवश्यक हो तो इसे सत्यापन के साथ बाल वर्गों द्वारा बढ़ाया जा सकता है। – rdlowrey

1

मुझे लगता है कि मुद्दा यह है कि आप इस प्रणाली के तहत परीक्षण होना चाहिए (अपने ढांचे) हो मॉडल ऑब्जेक्ट को तुरंत चालू करने के लिए new का उपयोग करने में सक्षम, और प्रत्येक परीक्षण को इसके गुणों के लिए अलग-अलग मान सेट करने की आवश्यकता होती है।

यदि ऐसा है, तो आप निर्माण पर गुणों के पूर्वनिर्धारित सेट को पॉप्युलेट करने के लिए एक सरल आधार वर्ग बना सकते हैं। नीचे दिया गया समाधान PHP 5.3 से late static binding का उपयोग करता है, लेकिन आप आसानी से बिना किसी चिमटा के परिणाम प्राप्त कर सकते हैं।

class MockModel 
{ 
    public static $properties; 

    public function __construct() { 
     if (isset(static::$properties) && is_array(static::$properties)) { 
      foreach (static::$properties as $key => $value) { 
       $this->$key = $value; 
      } 
     } 
    } 
} 

class MockBook extends MockModel { /* nothing needed */ } 

function testBookWithTitle() { 
    MockBook::$properties = array(
     'title' => 'To Kill a Mockingbird' 
    ); 
    $book = new MockBook; 
    self::assertEquals('To Kill a Mockingbird', $book->title); 
} 

जब तक आप अपने ढांचे के लिए new साथ उपयोग करने के लिए वर्ग के नाम प्रदान कर सकते हैं, इस काम करना चाहिए। यदि आपको अपने ढांचे के लिए एक ही कॉल के दौरान उसी मॉक क्लास के एक से अधिक उदाहरण बनाने में सक्षम होना आवश्यक है, तो आपको उपरोक्त को कुछ प्रकार के अनुक्रमण तंत्र के साथ बढ़ाने की आवश्यकता होगी।

+0

यह मॉडल परीक्षण के लिए है। मैं एक गलत लेखक और पुस्तक मॉडल बनाना चाहता हूं और उनके रिश्ते का परीक्षण करना चाहता हूं। जब मैं '$ लेखक-> पुस्तकें 'का उपयोग करता हूं, तो ढांचे को एक नई' बुक 'ऑब्जेक्ट को तुरंत चालू करने की आवश्यकता होती है और डेटा के साथ इसे बीज करने के लिए अपनी गुणों को पढ़ना पड़ता है और' लेखक 'से संबंध मानदंड निर्धारित करता है। तो नहीं, मैं वास्तव में अपने मॉक 'बुक' ऑब्जेक्ट को इंजेक्ट नहीं कर सकता क्योंकि यह गतिशील रूप से इन वस्तुओं को तुरंत चालू करने के लिए ढांचे का काम है। मुझे कोड में उस कक्षा को समेकित रूप से परिभाषित किए बिना उन गुणों के साथ स्मृति में 'लेखक' वर्ग को फेंकने की आवश्यकता है। –

+0

प्रश्न में मेरा आखिरी उदाहरण देखें। मुझे बस उन प्रकार के वर्गों को मेमोरी में लिखने में सक्षम होने की आवश्यकता है, बिना किसी कोडिंग के। मैंने सोचा कि मैं PHPUnit से मॉक ऑब्जेक्ट बिल्डर का लाभ उठा सकता हूं लेकिन मुझे यकीन नहीं है कि इसमें ऐसा करने की कार्यक्षमता है। –

+0

@ माइकब - मेरा अपडेट देखें। क्या आप यह हासिल करना चाहते हैं? –

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