Везде, где у вас есть 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
}
}
В тесте макет 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');
}