PHPUnit模拟抽象类的所有方法

时间:2013-04-23 14:26:49

标签: php unit-testing testing mocking phpunit

我有一个直接派生自PHPUnit_Framework_TestCase的PHPUnit测试用例。在这个类的测试中,我需要获得一些服务对象的模拟。此服务对象是由抽象基类定义的类型。该基类包含具体和抽象方法。我想得到一个完整的模拟事物(即所有方法被嘲笑)。我的问题是如何做到这一点。

- > getMock给我一个错误,因为抽象方法没有被模拟,只有具体的

- > getMockForAbstractClass模拟抽象方法而不是具体方法

我如何全部嘲笑它们?

(我正在使用PHPUnit 3.7.13)

2 个答案:

答案 0 :(得分:6)

只需调用->getMock('Class');即可模拟对象上的所有方法并实现所有抽象方法。

我不确定你哪里出错了,但事实如此,看似直截了当地写了一个样本。

如果它不适合你,我需要你想要做的重现案例

样品

<?php

class mockTest extends PHPUnit_Framework_TestCase {

    // Without expectations
    public function testMocking() {
        $x = $this->getMock('MockMe');
        $this->assertNull($x->foo());
        $this->assertNull($x->bar());
    }

    // With expectations
    public function testMocking2() {
        $x = $this->getMock('MockMe');
        $x->expects($this->once())->method('foo')->will($this->returnValue(true));
        $x->expects($this->once())->method('bar')->will($this->returnValue(true));
        $this->assertTrue($x->foo());
        $this->assertTrue($x->bar());
    }

}

abstract class MockMe {

    abstract public function foo();

    public function bar() {
        return 1 + $this->foo();
    }

}

可生产

PHPUnit 3.7.13 by Sebastian Bergmann.

..

Time: 0 seconds, Memory: 6.25Mb

OK (2 tests, 5 assertions)

答案 1 :(得分:4)

如果一个或多个抽象方法不公开,看起来$ this-&gt; getMock(...)将失败抽象类。

如果您不想使用衍生产品,可以在测试基类中添加类似的内容:

protected function getMockOfAbstractClass($originalClassName, $methods = array(), array $arguments = array(), $mockClassName = '', $callOriginalConstructor = TRUE, $callOriginalClone = TRUE, $callAutoload = TRUE) {
    if ($methods !== null) {
        $methods = array_unique(array_merge($methods,
        $this->getMethods($originalClassName, $callAutoload)));
    }
    return parent::getMock($originalClassName, $methods, $arguments, $mockClassName, $callOriginalConstructor, $callOriginalClone, $callAutoload);
}

private function getMethods($class, $autoload=true) {
    $methods = array();
    if (class_exists($class, $autoload) || interface_exists($class, $autoload)) {
        $reflector = new ReflectionClass($class);
        foreach ($reflector->getMethods( ReflectionMethod::IS_PUBLIC | ReflectionMethod::IS_ABSTRACT ) as $method) {
            $methods[] = $method->getName();
        }
    }
    return $methods;
}

改编自:Mocking concrete method in abstract class using phpunit