当前位置:  开发笔记 > 编程语言 > 正文

如何让PHPUnit MockObjects根据参数返回不同的值?

如何解决《如何让PHPUnitMockObjects根据参数返回不同的值?》经验,为你挑选了5个好方法。

我有一个PHPUnit模拟对象,'return value'无论它的参数是什么都返回:

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

我想要做的是根据传递给mock方法的参数返回一个不同的值.我尝试过类似的东西:

$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模拟对象根据其参数返回不同的值?如果是这样,怎么样?



1> 小智..:

使用回调.例如(直接来自PHPUnit文档):

getMock(
          'SomeClass', array('doSomething')
        );

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

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

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

在callback()中执行您想要的任何处理,并根据您的$ args返回结果.


这应该仅在极少数情况下使用.我建议使用[returnValueMap](http://www.phpunit.de/manual/3.6/en/test-doubles.html),因为它不需要在回调中编写自定义逻辑.
请注意,您可以通过传递数组来使用方法作为回调,例如`$ this-> returnCallback(array('MyClassTest','myCallback'))`.
你能提供文件的链接吗?我似乎无法用"谷歌"找到它

2> 小智..:

从最新的phpUnit文档:"有时,存根方法应根据预定义的参数列表返回不同的值.您可以使用returnValueMap()创建一个将参数与相应的返回值相关联的映射."

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


帖子中的链接是旧的,正确的是这里:[returnValueMap()](https://phpunit.de/manual/current/en/test-doubles.html#test-doubles.stubs.examples.StubTest5.php)

3> 小智..:

我有一个类似的问题(虽然略有不同......我不需要基于参数的不同返回值,但必须测试以确保将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次调用的顺序,但实际上这可能并不太糟糕.



4> Francis Lewi..:

您可能希望以OOP方式进行回调:

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];
    }
}
?>



5> Prokhor Sedn..:

这不是你要求的,但在某些情况下它可以帮助:

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

onConsecutiveCalls - 以指定的顺序返回值列表

推荐阅读
手机用户2502851955
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有