我正在为我的视图助手编写一些测试。这是我第一次想对嘲讽对象做点什么。我使用的是默认的PHPUnit嘲讽框架。
我写了一个函数来准备我的模拟对象:
private function getTestStub(){
$mockResult = array();
$mock = $this->getMock('My'Entity'Product');
$mock->expects($this->once())
->method('getId')
->will($this->returnValue(1));
$mock->expects($this->once())
->method('getName')
->will($this->returnValue('jan'));
$mock->expects($this->once())
->method('getWoonplaats')
->will($this->returnValue('Amsterdam'));
$mockResult[] = $mock;
return $mockResult;
}
现在,当使用这个存根进行测试时,我会得到以下错误:
Fatal error: Call to undefined method Mock_Product_129abca6::getId()
我在这里做错了什么?
PHPUnit查看您试图通过反射或get_class_methods
模拟的类。
模拟的类(如果存在)由模拟对象扩展。实现了类似的接口。您可以在代码本身中看到这是如何工作的。这是一堆代码生成的东西,如果你想看看并跟踪它是如何工作的,一个很好的起点是PHPUnit_Framework_MockObject_Generator::generate
。
在没有看到你试图模拟的类的情况下,我猜你的getter是__call
生成的"神奇"方法,类似于以下内容:
<?php
namespace My'Entity;
class Product
{
private $data = array();
public function __call($method, $args)
{
$set_or_get = strtolower(substr($method, 0, 3));
$prop = strtolower(substr($method, 3));
if ('get' === $set_or_get) {
return isset($this->data[$prop]) ? $this->data[$prop] : null;
} elseif ('set' === $set_or_get && isset($args[0])) {
$this->data[$prop] = $args[0];
} else {
throw new 'BadMethodCallException();
}
}
}
PHPUnit不能真正做到你想要的,因为你试图调用的方法实际上并不存在,而且神奇的__call
也不能按预期工作。要么是因为PHPUnit使用该方法本身,要么是其他原因(你必须深入挖掘才能找到它)。为了解决这个问题,您需要告诉PHPUnit您希望在mock中包含哪些方法。
// the second argument let's you define methods
$mock = $this->getMock('My'Entity'Product');
// try doing this instead
$mock = $this->getMock('My'Entity'Product', array('getId', 'getName', 'getWoonplaats'));
这个问题也有一些以上的好例子和解决方法。