嘲弄对象参数验证问题
Mockery object argument validation issue
考虑示例 类(很抱歉它太复杂了,但它尽可能简洁):
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 的同时测试应用程序:
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 returns 抛出 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 中是否有正确的方法来处理预期的实例参数?可能是我用错了?
你可以嘲笑应该接收一个 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 中有详细解释。
作为替代方案,documentation 建议使用 equalTo($object)。
例如:
$userRepository->shouldReceive('create')
->once()
->with(\Hamcrest\Core\IsEqual::equalTo(
new User(0, "Test", "Dummy", "fakelogin")));
考虑示例 类(很抱歉它太复杂了,但它尽可能简洁):
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 的同时测试应用程序:
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 returns 抛出 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 中是否有正确的方法来处理预期的实例参数?可能是我用错了?
你可以嘲笑应该接收一个 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 中有详细解释。
作为替代方案,documentation 建议使用 equalTo($object)。
例如:
$userRepository->shouldReceive('create')
->once()
->with(\Hamcrest\Core\IsEqual::equalTo(
new User(0, "Test", "Dummy", "fakelogin")));