Я хочу протестировать метод класса, который вызывает родительский метод с тем же именем. Есть ли способ сделать это?
class Parent { function foo() { echo 'bar'; } } class Child { function foo() { $foo = parent::foo(); return $foo; } } class ChildTest extend PHPUnit_TestCase { function testFoo() { $mock = $this->getMock('Child', array('foo')); //how do i mock parent methods and simulate responses? } }
Вы не издеваетесь и не заглушаете методы в тесте-тестировании (SUT). Если вы чувствуете, что вам нужно высмеять или заглушить метод в родительском элементе SUT, это, скорее всего, означает, что вы не должны использовать наследование, а агрегацию.
Вы издеваетесь над зависимостями субъекта-теста. Это означает, что любые другие объекты, которые SUT требует выполнения работы.
Подход, который работает для меня, – это реализация обертывания родительского вызова дочернего класса и, наконец, имитация этих оберток.
Вы изменили код:
class Parent { function foo() { echo 'bar'; } } class Child { function foo() { $foo = $this->parentFooCall(); return $foo; } function parentFooCall() { return parent::foo(); } } class ChildTest extend PHPUnit_TestCase { function testFoo() { $mock = $this->getMock('Child', array('foo', 'parentFooCall')); //how do i mock parent methods and simulate responses? } }
Вот как я это сделал, я понятия не имею, правильно ли это, но это работает:
class parentClass { public function whatever() { $this->doSomething(); } } class childClass extends parentClass { public $variable; public function subjectUnderTest() { $this->variable = 'whocares'; parent::whatever(); } }
теперь в тесте я делаю:
public function testSubjectUnderTest() { $ChildClass = $this->getMock('childClass', array('doSomething')) $ChildClass->expects($this->once()) ->method('doSomething'); $ChildClass->subjectUnderTest(); $this->assertEquals('whocares', $ChildClass->variable); }
что за ?
Мое рассуждение здесь состоит в том, что все, что я действительно хочу проверить, это то, была ли установлена моя переменная. я действительно не забочусь о том, что происходит в родительском методе, но так как вы не можете запретить вызов родительского метода, что я делаю, это mock зависимые методы родительского метода.
теперь иди и скажи мне, что я неправ 🙂
Я полностью согласен с @Gordon. У меня такая же проблема, но я пробовал несколько сложных концепций.
Мой сценарий похож
class Parent { // Actual-Parent Class function save() { // do something return $this } } class Child extends Parent { // Subject under test function save() { // do something return parent::save(); } }
Я создал еще один родительский класс с тем же именем «Родитель» и рассматриваю как заглушку и включаю мой класс-заглушку (родительский) и игнорирую фактического родителя (должен быть включен активный родительский класс в автоматическую загрузку, а родитель-заглушка должен быть включен)
class Parent { //Stub-Parent class function save() { return $this } }
Теперь я создаю макет объекта класса Child (через Mock-builder) и завершу свои тестовые примеры с завершением assertSame. 🙂
$this->assertSame($mock, $mock->save());
На мой взгляд, удовлетворительным решением является создание класса, который наследуется от вашего тестируемого класса и переопределяет реализацию метода, который вы хотите предоставить другой реализации. У этого есть свои недостатки: он не всегда работает, например, для уже переопределенных методов и для частных методов.
class Parent { function bar() { echo 'bar'; } } class Child extends Parent { function foo() { parent::bar(); echo 'foo'; } } class mockChild extends Child { function bar() { echo 'baz'; } } class ChildTest extends PHPUnit_TestCase { function testFoo() { $sut = new mockChild(); $sut->foo(); } }