模拟被测试的服务或测试实例

Mocking the service that is tested or test an instance

我最终与我们的一位同事讨论了如何设置用于测试服务的单元测试 class。

在设置测试用例时,我们中的一个建议模拟我们正在测试的实际 class,而另一个更喜欢创建 class 的实例并且只模拟依赖项。

假设我们正在测试 SomeService

一个解决方案是模拟实际服务并测试模拟:

$firstDependency  = //create mock for first dependency
$secondDependency = //create mock for second dependency
$this->someService = $this->getMockBuilder(SomeService::class)
     ->setMethods(null)
     ->setConstructorArgs(array($firstDependency, $secondDependency))
     ->getMock();

// continue testing $this->someService which is a mock

另一种解决方案是测试服务实例并仅模拟依赖项:

$firstDependency  = //create mock for first dependency
$secondDependency = //create mock for second dependency
$this->someService= new SomeService($firstDependency, $secondDependency);

// continue testing $this->someService which is direct instance of SomeService

以下哪些解决方案被认为是最佳实践?

答案最好参考官方 php-单位文档或其他可靠来源。

单元测试的目的是测试行为。模拟您要测试的对象实际上意味着您正在测试 'faked' 行为。测试预定义的行为有什么意义?

Don't mock class under test。不完全是 php-单位文档,但所有要点仍然有效。模拟 SUT 你最终测试的是模拟,而不是将在生产中使用的实际 class。

在测试抽象的情况下 class 创建模拟被认为是好的做法:

class AbstractClassTest extends PHPUnit_Framework_TestCase
{
    /**
     * Service under test in this case an abstract class
     */
    $this->sut;

    public function setUp()
    {
        $this->sut = $this->getMockForAbstractClass('My\Abstract\Class');
    }

    public function testMyAbstractClass()
    {
        $this->sut // do your test
    }
}