对于在其实现中组成另一个对象的对象,编写单元测试以便仅测试主要对象的最佳方法是什么?简单的例子:
class myObj {
public function doSomethingWhichIsLogged()
{
// ...
$logger = new logger('/tmp/log.txt');
$logger->info('some message');
// ...
}
}
我知道可以设计该对象,以便可以注入记录器对象依赖项,从而在单元测试中进行模拟,但情况并非总是如此 - 在更复杂的场景中,您确实需要组合其他对象或调用静态方法。
由于我们不想测试 logger 对象,只想测试 myObj,我们该如何继续?我们是否使用测试脚本创建一个存根“双”?就像是:
class logger
{
public function __construct($filepath) {}
public function info($message) {}
}
class TestMyObj extends PHPUnit_Framework_TestCase
{
// ...
}
这对于小对象来说似乎是可行的,但对于 SUT 依赖于返回值的更复杂的 API 来说会很痛苦。另外,如果您想像使用模拟对象一样测试对依赖项对象的调用,该怎么办?有没有一种方法可以模拟由 SUT 实例化的对象而不是传入的对象?
我已经阅读了有关模拟的手册页,但它似乎没有涵盖依赖项是组合而不是聚合的这种情况。你怎么做呢?
下列的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
}
}
有关模拟对象的更多信息可以找到在手册中 http://www.phpunit.de/manual/3.0/en/mock-objects.html.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)