كيف يمكنني الحصول على PHPUnit MockObjects لإرجاع قيم مختلفة بناءً على المعلمة؟

StackOverflow https://stackoverflow.com/questions/277914

سؤال

لقد حصلت على كائن وهمي PHPUnit الذي يعود 'return value' مهما كانت حججه:

// From inside a test...
$mock = $this->getMock('myObject', 'methodToMock');
$mock->expects($this->any))
     ->method('methodToMock')
     ->will($this->returnValue('return value'));

ما أريد أن أكون قادرًا على فعله هو إرجاع قيمة مختلفة بناءً على الوسائط التي تم تمريرها إلى الطريقة الوهمية.لقد حاولت شيئًا مثل:

$mock = $this->getMock('myObject', 'methodToMock');

// methodToMock('one')
$mock->expects($this->any))
     ->method('methodToMock')
     ->with($this->equalTo('one'))
     ->will($this->returnValue('method called with argument "one"'));

// methodToMock('two')
$mock->expects($this->any))
     ->method('methodToMock')
     ->with($this->equalTo('two'))
     ->will($this->returnValue('method called with argument "two"'));

ولكن هذا يتسبب في قيام PHPUnit بالشكوى إذا لم يتم استدعاء النموذج مع الوسيطة 'two', ، لذلك أفترض أن تعريف methodToMock('two') يكتب فوق تعريف الأول.

لذلك سؤالي هو:هل هناك أي طريقة للحصول على كائن PHPUnit وهمية لإرجاع قيمة مختلفة بناءً على وسيطاته؟وإذا كان الأمر كذلك، كيف؟

هل كانت مفيدة؟

المحلول

استخدم معاودة الاتصال بكم. مثلا (على التوالي من الوثائق PHPUnit):

<?php
class StubTest extends PHPUnit_Framework_TestCase
{
    public function testReturnCallbackStub()
    {
        $stub = $this->getMock(
          'SomeClass', array('doSomething')
        );

        $stub->expects($this->any())
             ->method('doSomething')
             ->will($this->returnCallback('callback'));

        // $stub->doSomething() returns callback(...)
    }
}

function callback() {
    $args = func_get_args();
    // ...
}
?>

والقيام بكل المعالجة التي تريدها في الاستدعاء () وإرجاع النتيجة على أساس سائط $ الخاص حسب الاقتضاء.

نصائح أخرى

ومن أحدث مستندات phpUnit: "في بعض الأحيان وسيلة فافات يجب أن تعود قيم مختلفة اعتمادا على قائمة محددة مسبقا من الحجج يمكنك استخدام <أ href = و". https://phpunit.de/manual/current/en/test- doubles.html # اختبار doubles.stubs.examples.StubTest5.php "يختلط =" noreferrer "> returnValueMap () لإنشاء خريطة يربط الحجج مع القيم المرجعة المقابلة".

$mock->expects($this->any())
    ->method('getConfigValue')
    ->will(
        $this->returnValueMap(
            array(
                array('firstparam', 'secondparam', 'retval'),
                array('modes', 'foo', array('Array', 'of', 'modes'))
            )
        )
    );

وكان لدي مشكلة مماثلة (على الرغم من مختلف قليلا ... لم أكن بحاجة قيمة الإرجاع مختلفة استنادا إلى الحجج، لكنه اضطر الى اختبار لضمان تمرير 2 مجموعات من الحجج لنفس الوظيفة). أنا عثر عليها باستخدام شيء من هذا القبيل:

$mock = $this->getMock();
$mock->expects($this->at(0))
    ->method('foo')
    ->with(...)
    ->will($this->returnValue(...));

$mock->expects($this->at(1))
    ->method('foo')
    ->with(...)
    ->will($this->returnValue(...));

وانها ليست مثالية، لأنه يتطلب أن ترتيب المكالمات 2 إلى فو () هو معروف، ولكن في الواقع هذا ربما ليست <م> من سيئة.

وربما كنت تريد أن تفعل رد بطريقة OOP:

<?php
class StubTest extends PHPUnit_Framework_TestCase
{
    public function testReturnAction()
    {
        $object = $this->getMock('class_name', array('method_to_mock'));
        $object->expects($this->any())
            ->method('method_to_mock')
            ->will($this->returnCallback(array($this, 'returnCallback'));

        $object->returnAction('param1');
        // assert what param1 should return here

        $object->returnAction('param2');
        // assert what param2 should return here
    }

    public function returnCallback()
    {
        $args = func_get_args();

        // process $args[0] here and return the data you want to mock
        return 'The parameter was ' . $args[0];
    }
}
?>

وانها ليست بالضبط ما تسأل، ولكن في بعض الحالات، يمكن أن تساعد في:

$mock->expects( $this->any() ) )
 ->method( 'methodToMock' )
 ->will( $this->onConsecutiveCalls( 'one', 'two' ) );

onConsecutiveCalls - إرجاع قائمة القيم في الترتيب المحدد

قم بتمرير مصفوفة ذات مستويين، حيث يكون كل عنصر عبارة عن مصفوفة من:

  • الأول هو معلمات الطريقة، والأقل هو قيمة الإرجاع.

مثال:

->willReturnMap([
    ['firstArg', 'secondArg', 'returnValue']
])

هل تعني شيئا مثل هذا؟

public function TestSomeCondition($condition){
  $mockObj = $this->getMockObject();
  $mockObj->setReturnValue('yourMethod',$condition);
}

وكان لي مشكلة مماثلة والتي لم أتمكن من العمل بها وكذلك (هناك القليل من المعلومات حول المستغرب لPHPUnit). في حالتي، لقد قدمت كل اختبار اختبار منفصل - إدخال المعروفة والانتاج المعروفة. أدركت أنني لم أكن بحاجة لجعل كائن وهمي جاك من بين كل الأعمال، وكنت بحاجة فقط واحد محدد لاختبار معين، وبالتالي أنا فصل الاختبارات ويمكن اختبار الجوانب الفردية من التعليمات البرمجية بصفتي منفصلة وحدة. أنا لست متأكدا إذا كان هذا قد يكون ينطبق عليك أم لا، ولكن هذا امر يرجع الى ما تحتاج إلى اختبار.

$this->BusinessMock = $this->createMock('AppBundle\Entity\Business');

    public function testBusiness()
    {
        /*
            onConcecutiveCalls : Whether you want that the Stub returns differents values when it will be called .
        */
        $this->BusinessMock ->method('getEmployees')
                                ->will($this->onConsecutiveCalls(
                                            $this->returnArgument(0),
                                            $this->returnValue('employee')                                      
                                            )
                                      );
        // first call

        $this->assertInstanceOf( //$this->returnArgument(0),
                'argument',
                $this->BusinessMock->getEmployees()
                );
       // second call


        $this->assertEquals('employee',$this->BusinessMock->getEmployees()) 
      //$this->returnValue('employee'),


    }

وجرب:

->with($this->equalTo('one'),$this->equalTo('two))->will($this->returnValue('return value'));
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top