phpunit mockobjects가 매개 변수를 기준으로 다른 값을 반환하도록하려면 어떻게해야합니까?

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

문제

반환하는 phpunit mock 객체가 있습니다 '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"'));

그러나 이로 인해 Mock이 주장과 함께 호출되지 않으면 PhPunit이 불만을 제기합니다. 'two', 그래서 나는 정의라고 가정합니다 methodToMock('two') 첫 번째 정의를 덮어 씁니다.

제 질문은 다음과 같습니다. phpunit 모의 개체가 인수에 따라 다른 가치를 반환 할 수있는 방법이 있습니까? 그렇다면 어떻게?

도움이 되었습니까?

해결책

콜백을 사용하십시오. EG (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();
    // ...
}
?>

콜백 ()에서 원하는 처리를 수행하고 적절한 $ args를 기준으로 결과를 반환하십시오.

다른 팁

최신 phpunit 문서에서 : "때로는 스터브 된 방법이 사전 정의 된 인수 목록에 따라 다른 값을 반환해야합니다. 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(...));

Foo ()에 대한 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']
])

또한 인수를 다음과 같이 반환 할 수 있습니다.

$stub = $this->getMock(
  'SomeClass', array('doSomething')
);

$stub->expects($this->any())
     ->method('doSomething')
     ->will($this->returnArgument(0));

당신이 볼 수 있듯이 조롱 문서, 방법 returnValue($index) 주어진 인수를 반환 할 수 있습니다.

이렇게 의미합니까?

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

나는 비슷한 문제를 겪을 수 없었습니다 (phpunit에 대한 정보는 놀랍게도 거의 없습니다). 제 경우에는 각 테스트를 별도의 테스트 - 알려진 입력 및 알려진 출력을 만들었습니다. 나는 jack-of-trades mock 객체를 만들 필요가 없다는 것을 깨달았고, 특정 테스트를 위해 특정 테스트 만 필요했기 때문에 테스트를 분리하고 내 코드의 개별 측면을 별도로 테스트 할 수 있습니다. 단위. 이것이 당신에게 적용 할 수 있는지 확실하지 않지만 테스트해야 할 사항에 달려 있습니다.

$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