有关这构成另一个对象作为其实现的一部分的对象,什么是写单元测试,以便只有原则对象被测试过的最好方法是什么?简单的例子:

class myObj { 
    public function doSomethingWhichIsLogged()
    {
        // ...
        $logger = new logger('/tmp/log.txt');
        $logger->info('some message');
        // ...
    }
}

我知道,物体可以被设计成记录器对象的依赖将被注入,因此在单元测试嘲笑,但事实并非总是如此 - 在更复杂的情况下,你需要编写其他物体或拨打电话到静态方法。

由于我们不想测试记录器对象,只有MyObj中,我们该如何进行呢?难道我们创建了一个存根“双规”与测试脚本?是这样的:

class logger
{
    public function __construct($filepath) {}
    public function info($message) {}
}

class TestMyObj extends PHPUnit_Framework_TestCase 
{
    // ...
}

这似乎对于小物体可行的,但是将是更复杂的API,其中SUT依赖于返回值的疼痛。另外,如果你想测试什么,在相同的依赖对象的调用是可以使用模仿对象?是否有嘲笑其由SUT实例化,而不是在被传递?对象的方法

我读过嘲笑男人页面,但它似乎并没有涵盖这一情况的依赖性由而非聚集。你怎么办呢?

有帮助吗?

解决方案

你似乎知道已经,混凝土类依赖性使得测试硬(或完全不可能)。你需要去耦这种依赖性。一个简单的变化,不打破现有的API,是默认为当前的行为,而是提供了一个钩来覆盖它。有许多的,这可以被实现的方式。

某些语言有可注入mock类为代码的工具,但我不知道这样的PHP什么。在大多数情况下,你可能会离开反正重构你的代码更好。

其他提示

下面的 troelskn 建议这里是你应该做的一个基本的例子。

<?php

class MyObj
{
    /**
     * @var LoggerInterface
     */
    protected $_logger;

    public function doSomethingWhichIsLogged()
    {
        // ...
        $this->getLogger()->info('some message');
        // ...
    }

    public function setLogger(LoggerInterface $logger)
    {
        $this->_logger = $logger;
    }

    public function getLogger()
    {
        return $this->_logger;
    }
}


class MyObjText extends PHPUnit_Framework_TestCase
{
    /**
     * @var MyObj
     */
    protected $_myObj;

    public function setUp()
    {
        $this->_myObj = new MyObj;
    }

    public function testDoSomethingWhichIsLogged()
    {
        $mockedMethods = array('info');
        $mock = $this->getMock('LoggerInterface', $mockedMethods);
        $mock->expects($this->any())
             ->method('info')
             ->will($this->returnValue(null));

        $this->_myObj->setLogger($mock);

        // do your testing
    }
}

约模拟对象的更多信息可以发现手动

有实际上是通过建立PHPUnit的同一人发布的PHP类重载一个合理的新的扩展。它可以让你在重载情况下,新的运营商,你不能重构代码,遗憾的是它并不那么简单安装在Windows上。

的URL是 http://github.com/johannes/php -test辅助细胞/斑点/主/

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top