phpunit মক জন্য নির্মাণকারী যুক্তি এড়ানো


85

কোন মক অবজেক্টের জন্য কনস্ট্রাক্টরকে কল করতে phpunit এড়ানোর উপায় কী? নইলে কনস্ট্রাক্টর আর্গুমেন্ট হিসাবে আমার কাছে একটি মক অবজেক্টের দরকার হবে, অন্যটির জন্য এটি etc. ইত্যাদি। এপিআই মনে হয়:

getMock($className, $methods = array(), array $arguments = array(),
        $mockClassName = '', $callOriginalConstructor = TRUE,
        $callOriginalClone = TRUE, $callAutoload = TRUE)

আমি এটি কাজ করতে না। এটি এখনও নির্ধারক যুক্তির বিষয়ে অভিযোগ করে এমনকি এমনকি $callOriginalConstructorমিথ্যাতে সেট করেও ।

কনস্ট্রাক্টরটিতে আমার কেবল একটি অবজেক্ট রয়েছে এবং এটি নির্ভরতা ইঞ্জেকশন। সুতরাং আমি মনে করি না যে সেখানে আমার কোনও ডিজাইনের সমস্যা আছে।

উত্তর:


139

আপনি ন্যায়বিচারের getMockBuilderপরিবর্তে ব্যবহার করতে পারেন getMock:

$mock = $this->getMockBuilder('class_name')
    ->disableOriginalConstructor()
    ->getMock();

বিভাগে দেখুন "টেস্ট দ্বিগুণ" মধ্যে PHPUnit এর ডকুমেন্টেশন বিস্তারিত জানার জন্য।

যদিও আপনি এটি করতে পারেন, এটির প্রয়োজন না হওয়াই আরও ভাল। আপনি আপনার কোডটি রিফ্যাক্টর করতে পারেন তাই কংক্রিটের ক্লাসের পরিবর্তে (কনস্ট্রাক্টর সহ) ইঞ্জেকশন লাগানো দরকার, আপনি কেবল ইন্টারফেসের উপর নির্ভর করেন। এর অর্থ আপনি পিএইচপিউইনিটকে কনস্ট্রাক্টর আচরণটি পরিবর্তন করতে না বলে ইন্টারফেসটিকে মক বা স্টক করতে পারেন।


এটি আমার পক্ষে দুর্দান্ত কাজ করে। এটি উদাহরণস্বরূপ 10.3 হওয়া উচিত। আমি পোস্টটি সম্পাদনা করার চেষ্টা করেছি কিন্তু খুব কম সম্পাদনা হওয়ার কারণে এসও এটিকে পিছনে ফেলেছিল।
ম্যাথু

ধন্যবাদ @ লিতিথউইন। উত্তর আপডেট করেছেন।
dave1010

42

আপনি এখানে যান:

    // Get a Mock Soap Client object to work with.
    $classToMock = 'SoapClient';
    $methodsToMock = array('__getFunctions');
    $mockConstructorParams = array('fake wsdl url', array());
    $mockClassName = 'MyMockSoapClient';
    $callMockConstructor = false;
    $mockSoapClient = $this->getMock($classToMock,
                                     $methodsToMock,
                                     $mockConstructorParams,
                                     $mockClassName,
                                     $callMockConstructor);

এটি প্রায় আমি যা চাই তা মনে হচ্ছে। আমি মজা করার জন্য শুধুমাত্র ক্লাস সহ গেটমকে কল করতে চাই এবং $ কলমকনস্ট্রাক্টর। কীভাবে? এর মতো কিছু: $ এটি-> getMock ($ ClassToMock, $ কলমককন্সট্রাক্টর)। আমি কেবলমাত্র পিএইচপিউইনিতের উত্সে যেতে এবং এটিকে ডিফল্ট = মিথ্যাতে পরিবর্তন করতে পারি think
গুটজফটার

4
আমি টেস্টকেস.এফপি-তে ডিফল্টটিকে মিথ্যাতে পরিবর্তন করেছি। আপনি মনে করেন এটি ডিফল্টরূপে মিথ্যা জন্য সেট করা হবে। কোনও কনস্ট্রাক্টরকে উপহাস করা খুব অদ্ভুত বলে মনে হচ্ছে
গুটজফটার

দুর্দান্ত উত্তর। ঠিক আমি যা খুঁজছিলাম
হেডেস

4

সংযোজন হিসাবে, আমি expects()আমার উপহাসকৃত বস্তুর সাথে কলগুলি সংযুক্ত করতে এবং তারপরে কনস্ট্রাক্টরকে কল করতে চেয়েছিলাম । PHPUnit 3.7.14 এ, আপনি কল করার সময় যে বস্তুটি ফিরে আসে disableOriginalConstructor()তা আক্ষরিক অর্থে একটি অবজেক্ট।

// Use a trick to create a new object of a class
// without invoking its constructor.
$object = unserialize(
sprintf('O:%d:"%s":0:{}', strlen($className), $className)

দুর্ভাগ্যক্রমে, পিএইচপি 5.4 এ একটি নতুন বিকল্প রয়েছে যা তারা ব্যবহার করছেন না:

রিফ্লেকশনক্লাস :: নতুন ইনস্ট্যান্স উইথআউট কনস্ট্রাক্টর

যেহেতু এটি উপলভ্য ছিল না, তাই আমাকে ম্যানুয়ালি ক্লাস প্রতিবিম্বিত করতে হয়েছিল এবং তারপরে কনস্ট্রাক্টরকে অনুরোধ করতে হয়েছিল।

$mock = $this->getMockBuilder('class_name')
    ->disableOriginalConstructor()
    ->getMock();

$mock->expect($this->once())
    ->method('functionCallFromConstructor')
    ->with($this->equalTo('someValue'));

$reflectedClass = new ReflectionClass('class_name');
$constructor = $reflectedClass->getConstructor();
$constructor->invoke($mock);

দ্রষ্টব্য, যদি functionCallFromConstructহয় তবে protectedআপনাকে বিশেষভাবে ব্যবহার করতে হবে setMethods()যাতে সুরক্ষিত পদ্ধতিটিকে উপহাস করা যায়। উদাহরণ:

    $mock->setMethods(array('functionCallFromConstructor'));

setMethods()expect()কল করার আগে অবশ্যই ফোন করা উচিত । ব্যক্তিগতভাবে, আমি পরে disableOriginalConstructor()কিন্তু আগে এই চেইন getMock()


এটি কোনও কোড গন্ধ কিনা তা ধারণা নেই, তবে এটি আমার পক্ষে দুর্দান্ত কাজ করেছে এবং আমি আপনাকে ধন্যবাদ জানাতে চাই।
দেববানানা

1

কনস্ট্রাক্টর আর্গুমেন্ট হিসাবে আপনাকে পাস করার জন্য সম্ভবত একটি স্টাব তৈরি করতে হবে। তারপরে আপনি সেই শৃঙ্খলটিকে মেক অবজেক্টগুলি ভেঙে ফেলতে পারেন।


1

বিকল্পভাবে আপনি ডিফল্ট কনস্ট্রাক্টর এর কলিং রোধ করতে getMock এ একটি পরামিতি যুক্ত করতে পারেন ।

$mock = $this->getMock(class_name, methods = array(), args = array(), 
        mockClassName = '', callOriginalConstructor = FALSE);

তবুও, আমার মনে হয় ডেভ 1010 এর উত্তরটি দেখতে ভাল লাগছে, এটি কেবল সম্পূর্ণতার জন্য।


1

এই প্রশ্নটি কিছুটা পুরানো তবে নতুন দর্শকদের জন্য আপনি createMockপদ্ধতিটি ব্যবহার করে এটি করতে পারেন (পূর্বে বলা createTestDoubleহয়েছিল এবং v5.4.0 এ পরিচিত হয়েছিল)।

$mock = $this->createMock($className);

আপনি PHPUnit\Framework\TestCaseক্লাসটি থেকে প্রাপ্ত নীচের কোডটিতে দেখতে পাবেন (ইন phpunit/src/framework/TestCase.php), এটি মূলত আসল নির্মাণকারীকে কল না করে একটি মক অবজেক্ট তৈরি করবে

/** PHPUnit\Framework\TestCase::createMock method */
protected function createMock(string $originalClassName): MockObject
{
    return $this->getMockBuilder($originalClassName)
                ->disableOriginalConstructor()
                ->disableOriginalClone()
                ->disableArgumentCloning()
                ->disallowMockingUnknownTypes()
                ->getMock();
}

0

পিএইচপিউনিটটি উপহাসকৃত বস্তুগুলিতে কনস্ট্রাক্টরকে কল করার জন্য ডিজাইন করা হয়েছে; এটি রোধ করার জন্য আপনারও উচিত:

  1. আপনাকে যে উপহাস করতে সমস্যা হচ্ছে তার মধ্যে নির্ভরতা হিসাবে একটি মক অবজেক্ট ইনজেক্ট করুন
  2. এমন একটি পরীক্ষার শ্রেণি তৈরি করুন যা আপনি কল করার চেষ্টা করছেন এমন ক্লাসকে প্রসারিত করে যা পিতামাত্ত্র কনস্ট্রাক্টরকে কল করে না
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.