【问题标题】:Mockery object argument validation issue嘲弄对象参数验证问题
【发布时间】:2015-07-07 05:04:33
【问题描述】:

考虑示例类(为它如此复杂而道歉,但它尽可能苗条):

class RecordLookup
{
    private $records = [
        13 => 'foo',
        42 => 'bar',
    ];

    function __construct($id)
    {
        $this->record = $this->records[$id];
    }

    public function getRecord()
    {
        return $this->record;
    }
}

class RecordPage
{
    public function run(RecordLookup $id)
    {
        return "Record is " . $id->getRecord();
    }
}

class App
{
    function __construct(RecordPage $page, $id)
    {
        $this->page = $page;
        $this->record_lookup = new RecordLookup($id);
    }

    public function runPage()
    {
        return $this->page->run($this->record_lookup);
    }
}

我想在模拟 RecordPage 的同时测试 App:

class AppTest extends \PHPUnit_Framework_TestCase
{
    function testAppRunPage()
    {
        $mock_page = \Mockery::mock('RecordPage');

        $mock_page
            ->shouldReceive('run')
            ->with(new RecordLookup(42))
            ->andReturn('bar');

        $app = new App($mock_page, 42);

        $this->assertEquals('Record is bar', $app->runPage());
    }
}

注意:预期的对象参数->with(new RecordLookup(42))

我希望这会通过,但是 Mockery 返回 throws No matching handler found for Mockery_0_RecordPage::run(object(RecordLookup)). Either the method was unexpected or its arguments matched no expected argument list for this method

我假设这是因为对通过with()new RecordLookup(42) === new RecordLookup(42) 预期的参数进行了严格比较,结果为假。注意new RecordLookup(42) == new RecordLookup(42) 评估为真,所以如果有某种方式可以放松比较,它会解决我的问题。

在 Mockery 中是否有适当的方法来处理预期的实例参数?可能是我用错了?

【问题讨论】:

    标签: php phpunit mockery


    【解决方案1】:

    你可以告诉 mocky 应该接收一个 RecordLookup 实例(任何):

    $mock_page
            ->shouldReceive('run')
            ->with(\Mockery::type('RecordLookup'))
            ->andReturn('bar');
    

    但这将匹配任何 RecordLookup 实例。如果您需要在对象内部挖掘并检查它的值是否为 42,那么您可以使用自定义验证器:

    $mock_page
            ->shouldReceive('run')
            ->with(\Mockery::on(function($argument) {
                return 
                     $argument instanceof RecordLookup && 
                     'bar' === $argument->getRecord()
                ;
            }))
            ->andReturn('bar');
    

    还有更多的选择,在the docs中有很好的解释。

    【讨论】:

    • 谢谢!我实际上刚刚发现了这个问题跟踪:github.com/padraic/mockery/issues/328,它涵盖了相同的主题。
    • @gontrollez,谢谢你,你刚刚救了我。
    • 一年后再次感谢您。
    【解决方案2】:

    作为替代方案,documentation 建议使用 equalTo($object)。

    例如:

    $userRepository->shouldReceive('create')
                ->once()
                ->with(\Hamcrest\Core\IsEqual::equalTo(
                    new User(0, "Test", "Dummy", "fakelogin")));
    

    【讨论】:

      猜你喜欢
      • 2016-06-22
      • 2017-09-01
      • 2019-02-09
      • 2019-08-03
      • 2014-10-27
      • 2019-02-08
      • 2019-08-10
      • 2015-02-04
      • 2016-07-12
      相关资源
      最近更新 更多