我正在尝试在管理数据库连接的类上使用TDD。但是
:memory:
基本上我想这样做:
class ConnectionManager {
...
public function getConnection($name) {
$params = $this->lookup($name);
return new \PDO($params['spec'], $params['username'], $params['password']);
}
}
在我的测试跑步者中:
class ConnectionManagerTest extends \PHPUnit_Framework_TestCase {
public function testGetConnection() {
$cxn = new ConnectionManager();
$this->assertNotNull($cxn->getConnection('test')); // or whatever
}
}
不知怎的,我想使用PDO类的模拟。我唯一的选择是向测试类构造函数或其方法之一添加显式参数吗?我尝试使用Mockery文档中的'Instance mocking',但是因为我使用自动加载会导致'致命错误无法重新声明类'(duh)。
我不想用纯粹用于测试的代码来污染合同,但这是我唯一的选择吗?
感谢您的帮助
答案 0 :(得分:3)
这看起来像依赖注入可以帮助您的情况。网上有很多很好的文章描述了这种技术(这里是wikipedia overview),而前面的stack overflow answer给出了该技术的简明解释(例子是Java中的,但它应该解释模式并且可以很容易地转换成另一种语言。)
关于“不想用纯粹用于测试的合同污染代码”的观点是一个有趣的观点。我认为,随着您获得TDD的更多经验,您会发现,编写易于测试的代码,编写良好的干净代码,实质上是同一枚硬币的两面。 TDD的一个微妙的力量(正确实践)是它引导您走向一个良好,干净的设计,可以很容易地与您的应用程序一起成长。通过遵循将测试放在您设计代码的核心的方法,您实际上是从客户端的角度设计代码,这样可以更清晰地接口代码中的不同组件,并最终使使用这些接口的代码更加清晰。
依赖注入是遵循TDD时应用的常用技术,并且是这些要点的一个很好的例证。一方面它对测试有效,因为它允许您在测试时轻松交换组件,这样您就可以避免必须调用数据库,模拟和验证组件之间的交互等等。但是,它还支持通常良好的设计,因为它会引导您实现低耦合和灵活的设计(例如,如果您是依赖注入数据库的访问权限,那么将数据源从数据库更改为其他数据非常简单技术)。