【问题标题】:how to create a mock in a model test case如何在模型测试用例中创建模拟
【发布时间】:2012-06-22 07:45:56
【问题描述】:
也许我做错了。
我想测试一个模型(抗体)的 beforeSave 方法。此方法的一部分调用关联模型(物种)上的方法。我想模拟 Species 模型,但找不到方法。
是否有可能或者我正在做一些违背 MVC 模式的事情,从而试图做一些我不应该做的事情?
class Antibody extends AppModel {
public function beforeSave() {
// some processing ...
// retreive species_id based on the input
$this->data['Antibody']['species_id']
= isset($this->data['Species']['name'])
? $this->Species->getIdByName($this->data['Species']['name'])
: null;
return true;
}
}
【问题讨论】:
标签:
unit-testing
cakephp
mocking
phpunit
cakephp-2.1
【解决方案1】:
假设您的 Species 模型是由 cake 由于关系创建的,您可以简单地执行以下操作:
public function setUp()
{
parent::setUp();
$this->Antibody = ClassRegistry::init('Antibody');
$this->Antibody->Species = $this->getMock('Species');
// now you can set your expectations here
$this->Antibody->Species->expects($this->any())
->method('getIdByName')
->will($this->returnValue(/*your value here*/));
}
public function testBeforeFilter()
{
// or here
$this->Antibody->Species->expects($this->once())
->method('getIdByName')
->will($this->returnValue(/*your value here*/));
}
【解决方案2】:
嗯,这取决于注入“物种”对象的方式。
它是通过构造函数注入的吗?通过二传手?是继承的吗?
这是一个构造函数注入对象的示例:
class Foo
{
/** @var Bar */
protected $bar;
public function __construct($bar)
{
$this->bar = $bar;
}
public function foo() {
if ($this->bar->isOk()) {
return true;
} else {
return false;
}
}
}
那么你的测试会是这样的:
public function test_foo()
{
$barStub = $this->getMock('Overblog\CommonBundle\TestUtils\Bar');
$barStub->expects($this->once())
->method('isOk')
->will($this->returnValue(false));
$foo = new Foo($barStub);
$this->assertFalse($foo->foo());
}
这个过程与 setter 注入对象完全一样:
public function test_foo()
{
$barStub = $this->getMock('Overblog\CommonBundle\TestUtils\Bar');
$barStub->expects($this->once())
->method('isOk')
->will($this->returnValue(false));
$foo = new Foo();
$foo->setBar($barStub);
$this->assertFalse($foo->foo());
}