Имитация конкретного метода в абстрактном классе с использованием phpunit

Есть ли какие-нибудь хорошие способы имитировать конкретные методы абстрактно классы, использующие PHPUnit?

На данный момент я обнаружил следующее:

  • expect () -> will () отлично работает с использованием абстрактных методов
  • Это не работает для конкретных методов. Вместо этого запускается исходный метод.
  • Использование mockbuilder и передача всех абстрактных методов и конкретного метода в setMethods () работает. Однако он требует, чтобы вы указали все абстрактные методы, что делает тест хрупким и слишком многословным.
  • MockBuilder :: getMockForAbstractClass () игнорирует setMethod ().


Вот несколько модульных тестов, иллюстрирующих вышеуказанные пункты:

abstract class AbstractClass {
    public function concreteMethod() {
        return $this->abstractMethod();
    }

    public abstract function abstractMethod();
}


class AbstractClassTest extends PHPUnit_Framework_TestCase {
    /**
     * This works for abstract methods.
     */
    public function testAbstractMethod() {
        $stub = $this->getMockForAbstractClass('AbstractClass');
        $stub->expects($this->any())
                ->method('abstractMethod')
                ->will($this->returnValue(2));

        $this->assertSame(2, $stub->concreteMethod()); // Succeeds
    }

    /**
     * Ideally, I would like this to work for concrete methods too.
     */
    public function testConcreteMethod() {
        $stub = $this->getMockForAbstractClass('AbstractClass');
        $stub->expects($this->any())
                ->method('concreteMethod')
                ->will($this->returnValue(2));

        $this->assertSame(2, $stub->concreteMethod()); // Fails, concreteMethod returns NULL
    }

    /**
     * One way to mock the concrete method, is to use the mock builder,
     * and set the methods to mock.
     *
     * The downside of doing it this way, is that all abstract methods
     * must be specified in the setMethods() call. If you add a new abstract
     * method, all your existing unit tests will fail.
     */
    public function testConcreteMethod__mockBuilder_getMock() {
        $stub = $this->getMockBuilder('AbstractClass')
                ->setMethods(array('concreteMethod', 'abstractMethod'))
                ->getMock();
        $stub->expects($this->any())
                ->method('concreteMethod')
                ->will($this->returnValue(2));

        $this->assertSame(2, $stub->concreteMethod()); // Succeeds
    }

    /**
     * Similar to above, but using getMockForAbstractClass().
     * Apparently, setMethods() is ignored by getMockForAbstractClass()
     */
    public function testConcreteMethod__mockBuilder_getMockForAbstractClass() {
        $stub = $this->getMockBuilder('AbstractClass')
                ->setMethods(array('concreteMethod'))
                ->getMockForAbstractClass();
        $stub->expects($this->any())
                ->method('concreteMethod')
                ->will($this->returnValue(2));

        $this->assertSame(2, $stub->concreteMethod()); // Fails, concreteMethod returns NULL
    }
}
15
задан CheeseSucker 7 November 2011 в 17:36
поделиться