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