无论你在测试的方法中处于什么位置,你都注定要失败。将实例化提取到同一类的新方法----。这允许您创建受测类的部分模拟,该模拟从新方法返回存根或模拟值。new XXX(...)
createSomeClass(...)
class someClass {
public function someFoo($var) {
$model = $this->createSomeClass(); // call method instead of using new
model->someOtherFoo($var);
}
public function createSomeClass() { // now you can mock this method in the test
return new someClass();
}
public function someOtherFoo($var){
// some code which has to be mocked
}
}
在测试中,mock 在你调用的实例中,在从第一个模拟调用返回的实例中 mock。createSomeClass()
someFoo()
someOtherFoo()
function testSomeFoo() {
// mock someOtherFoo() to ensure it gets the correct value for $arg
$created = $this->getMock('someClass', array('someOtherFoo'));
$created->expects($this->once())
->method('someOtherFoo')
->with('foo');
// mock createSomeClass() to return the mock above
$creator = $this->getMock('someClass', array('createSomeClass'));
$creator->expects($this->once())
->method('createSomeClass')
->will($this->returnValue($created));
// call someFoo() with the correct $arg
$creator->someFoo('foo');
}
请记住,由于该实例正在创建同一类的另一个实例,因此通常会涉及两个实例。您可以在此处使用相同的模拟实例,如果它使它更清晰。
function testSomeFoo() {
$fixture = $this->getMock('someClass', array('createSomeClass', 'someOtherFoo'));
// mock createSomeClass() to return the mock
$fixture->expects($this->once())
->method('createSomeClass')
->will($this->returnValue($fixture));
// mock someOtherFoo() to ensure it gets the correct value for $arg
$fixture->expects($this->once())
->method('someOtherFoo')
->with('foo');
// call someFoo() with the correct $arg
$fixture->someFoo('foo');
}