【发布时间】:2011-07-13 23:27:20
【问题描述】:
我一直在研究如何将单元测试覆盖率添加到用 PHP 编写的大型现有代码库中。静态类和可实例化类中的许多函数都会调用库或实例化对象,以获得与内存缓存和数据库的连接。它们通常看起来像这样:
public function getSomeData() {
$key = "SomeMemcacheKey";
$cache = get_memcache();
$results = $cache->get($key);
if (!$results) {
$database = new DatabaseObject();
$sql = "SELECT * from someDatabase.someTable";
$results = $database->query($sql);
$cache->set($key, $results);
}
return $results;
}
我和我的同事目前正在尝试通过 PHPUnit 为我们正在编写的一些新类实现覆盖。我试图找到一种方法,以隔离的方式为我们现有代码库中的函数创建单元测试,这些函数类似于上面的伪代码,但没有成功。
我在 PHPUnit 文档中看到的示例都依赖于类中的某些方法,通过该方法可以将模拟对象附加到它,例如:
$objectBeingTested->attach($mockObject); 我查看了 SimpleUnit,在那里看到了同样的东西,模拟对象通过其构造函数传递到类中。这不会为实例化自己的数据库对象的函数留下太多空间。
有什么方法可以模拟出这类调用吗?我们可以使用另一个单元测试框架吗?还是我们将来必须更改我们使用的模式以促进单元测试?
我想做的是能够在运行测试时用模拟类替换整个类。例如,可以将 DatabaseObject 类替换为模拟类,并且在测试期间实例化的任何时候,它实际上都是模拟版本的实例。
我的团队一直在谈论重构我们在新代码中访问数据库和 memcache 的方法,可能使用单例。我想如果我们以这样一种方式编写单例,它自己的实例可以被一个模拟对象替换,那可能会有所帮助......
这是我第一次涉足单元测试。如果我做错了,请说出来。 :)
谢谢。
【问题讨论】:
-
似乎没有办法,因为紧密的情侣。建议看看 Symfony DI。
标签: php database unit-testing mocking phpunit