单元测试遗留的php应用程序 - 如何防止意外的数据库调用

时间:2017-08-17 00:00:07

标签: php mysql database unit-testing phpunit

我将单元测试添加到使用MySQL兼容数据库的旧PHP应用程序中。我想写一些不接触数据库的真正的单元测试。

我应该如何避免意外使用数据库连接?

应用程序的许多部分使用静态方法调用来获取对数据库连接包装器对象的引用。如果我正在查看其中一个调用,我知道如何使用依赖注入和测试双精度来避免从测试中访问数据库,但我不知道如何处理我所有的数据库查询#&# 39;任何时候都不看,这可能是我尝试测试的方法在调用堆栈中的某种程度。

我考虑过将一个公共方法添加到数据库访问类中,该方法将从PHPUnit引导程序文件中调用,并设置一个静态变量以使任何进一步的数据库访问都无法进行,但我并不热衷于添加应用程序代码的一个函数,纯粹是为了在生产中调用时会有害的测试。

1 个答案:

答案 0 :(得分:1)

将测试添加到遗留应用程序可能很复杂,尤其是单元测试。您可能遇到的主要问题是大多数测试都难以编写并且很容易变得难以理解,因为它们涉及大量的设置和模拟。与此同时,你可能没有太多自由来重构它们,因此它们变得更容易测试,因为这将导致代码库中的连锁反应。

这就是为什么我通常更喜欢端到端测试。您可以覆盖大量的地面而无需测试接近实现,并且当您希望稍后进行大规模重构或迁移遗留代码库时,这些测试通常更有用,因为您确保您使用的最重要的功能仍然有效如预期的那样。

对于这种方法,您需要测试数据库,而不是实时数据库。一开始,制作副本可能最容易,但是从头开始创建一个带有一些测试夹具的精简数据库是绝对值得的。然后你可以使用像selenium这样的东西通过网络界面测试你的应用程序,描述你在网站上采取的行动,比如去网址x,填写表格并提交它并描述预期的结果,就像我应该在网址上现在,数据库中应该有一个新条目。正如您所看到的,这些类型的测试与您在网站上看到的非常接近,而不是围绕实现或单个单元。这实际上是因为在迁移中你可能想要删除大块并重写它们。单元测试将变得完全无用,因为实现可能会发生巨大变化,但那些描述网站功能的end2end-tests仍然有效。

有多种方法可以解决这个问题。如果您熟悉PHPUnit,可能需要尝试使用selenium-extension。你应该在网上找到这方面的教程,例如:https://www.sitepoint.com/using-selenium-with-phpunit/

这类测试的另一个流行选项是BehatMinkExtension。在这两种情况下,最困难的部分是设置selenium,但是一旦你能够编写一个简单的测试,例如,它会进入你的首页并检查一些文本片段并使其运行。你可以非常快速地编写测试。

这些测试的一个重大缺点是它们非常慢,因为它们执行完整的Web请求,在某些情况下还需要等待JavaScript。所以你可能不应该测试一切。而是尝试专注于最重要的功能。如果你有一些电子商务项目,可能会通过一个非常通用的结账程序。然后展开对您很重要的不同变体,例如登录用户与新用户或将凭证添加到购物篮。另一个好的方法是编写非常愚蠢的测试,只检查你的网址是否实际可访问,所以转到网址并检查状态代码和一些预期的文本片段。在确保您的应用程序正常运行方面,这些并不是非常有用,但它们仍然可以为您提供一些安全性,以确定是否出现了一些随机的500错误。

这可能是确保您的应用程序正常运行并使其更容易升级,重构或迁移您的应用程序或部分应用程序的最佳方法。此外,无论何时添加新功能,请尝试为它们编写一些实际的单元测试。如果它们与代码的旧部分没有太多联系,那可能是最简单的。在最好的情况下,您不必过多担心数据库,因为您可以使用您在测试中自己准备的某些实例替换从数据库获得的数据,然后只测试任何功能。显然,如果它像一个简单的东西,我们想要一个将这些数据添加到数据库的表单,你可能仍然不想编写单元测试,而是编写其中一个更大的端到端测试。