我正在尝试对我创建的类进行单元测试,但大多数类都处理数据库。我已经让非数据库相关的类在本地测试得很好,但是当涉及到使用数据库时,我很难过,特别是远程。该指南显示使用PDO访问似乎被转储到XML文件的本地数据库,因此它对我来说没用,因为我的数据库位于Amazon云中并使用pg_ *函数连接到Postgres数据库。
是否有类似情况的好例子或任何人都可以提供任何帮助?我不知道我是否应该在文件中拥有本地版本的数据库或连接到远程服务器。如果我必须连接,我该怎么做才能使它工作?
结论
我和项目架构师进行了调查,我们确定最好实现ORM,因为数据库没有抽象。在此之前,数据库测试将暂停。一旦到位,我确信PHPUnit手册会更有意义。
答案 0 :(得分:5)
简短的回答是Read The Fine Manual entry on database testing at the PHPUnit manual。
关于单元测试要记住的第一件事是它需要在所有其他组件的 隔离 中执行。通常,使用dependency injectionwikipedia等控制反转(IoC)技术可以简化这一目标。当您的类在构造函数方法中明确询问它们的依赖关系时,它是mockphpunit这些依赖项的简单操作,以便您可以单独测试剩余的代码。
测试与模型交互的代码有点不同。通常,将模型注入需要访问它们的类中是不切实际或不可取的。您的模型通常是“哑”数据结构,暴露有限或无能力。因此,通常可接受(在可测试性方面)在您注入的类中动态实例化您的模型。不幸的是,这使得测试数据库代码变得困难,因为正如PHPUnit文档所指出的那样:
[T]数据库本质上是代码的全局输入变量
那么,如果不直接注入模型,您如何隔离和测试与数据库交互的代码?最简单的方法是使用test fixturesphpunit。
由于您肯定已经在使用PDO
或构建在PDO
上的ORM库(对吗?),
设置fixtures就像为基本的SQLite数据库或XML文件播种一样简单,以适应您的测试用例,并在测试与数据库交互的代码时使用该特殊的数据库连接。您可以在PHPUnit引导文件中指定此连接,但在语义上可能更适合设置PHPUnit Database TestCasephpunit。
测试数据库代码的普遍接受的最佳实践步骤(这些也在关于数据库测试的PHPUnit文档中得到了回应):
因此,总而言之,您需要做的就是创建一个“虚拟”数据库夹具,让您的代码与已知数据交互,而不是在生产中使用的实际数据库。此方法允许您成功隔离测试中的代码,因为它处理已知数据,这意味着您可以对数据库操作的结果进行特定/可测试的断言。
<强>更新强>
因为如果你想要提升可测试性,它对于你的代码中不做什么是一个非常有用的指南,我正在添加一个指向Misko Hevery How to Write 3v1L, Untestable Code的链接。它并没有特别涉及数据库测试,但它仍然有用。快乐的测试!
更新2
我想回应关于推迟模型测试的评论,因为现有的代码库没有为数据库访问实现PDO
:
您的模型不必使用PDO来实现PHPUnit的DbUnit扩展。
如果您使用PDO,它将使您的生活更轻松,但您不需要这样做。比如说,您已经使用PHP的内置pg_*
PostgreSQL函数构建了应用程序。 PHPUnit仍允许您指定灯具,它仍然可以为每个测试重建它们 - 您只需要在对DbUnit扩展用于其灯具的相同资源执行测试时指向您的连接。