开始为数据访问代码编写集成测试之前,我们要做的第一件事是决定如何配置测试用例。
我们有两种选择:正确的一种和错误的一种。
不幸的是,许多开发人员选择错误。
我们如何避免犯同样的错误?
我们可以遵循以下三个规则来做出正确的决定:
规则1:我们必须测试我们的应用程序
这个规则似乎很明显。 可悲的是,许多开发人员在集成测试中使用了不同的配置,因为它使测试通过。
这是个错误!
我们应该问自己一个问题:
当我们使用生产环境中使用的配置时,我们是否要测试数据访问代码是否正常工作?还是只希望测试通过?
我认为答案很明显。 如果我们在集成测试中使用其他配置,则不会测试数据访问代码在生产环境中的行为。 我们正在运行集成测试时测试它的行为。
换句话说,当我们将应用程序部署到生产环境时,我们无法验证数据访问代码是否按预期工作。
这听起来像是一个值得的目标?
如果要在使用生产配置时测试我们的数据访问代码是否工作,则应遵循以下简单规则:
- 我们应该使用配置应用程序持久层的相同配置类或配置文件来配置测试。
- 我们的测试应该使用与应用程序相同的事务行为。
这些规则有两个主要好处:
- 因为我们的集成测试使用与应用程序完全相同的配置并共享相同的事务行为,所以我们的测试可帮助我们验证将应用程序部署到生产环境时数据访问代码是否按预期工作。
- 我们不必维护其他配置。 换句话说,如果我们对生产配置进行更改,则可以在不对集成测试的配置进行任何更改的情况下测试该更改不会破坏任何内容。
规则2:我们可以打破规则1
在软件开发中没有普遍真理。 每个原则规则仅在特定条件下有效。 如果条件发生变化,我们必须重新评估这些原则。 这也适用于第一条规则。
这是一个很好的起点,但是有时我们必须打破它。
如果我们要对配置进行测试特定的更改,则必须执行以下步骤:
- 找出更改的原因。
- 列出更改的利弊。
- 如果收益大于弊端,则允许我们更改测试的配置。
- 记录进行此更改的原因。 之所以如此重要,是因为如果我们发现这样做是一个坏主意,它使我们有可能撤销更改。
例如,当这些测试在开发环境(即开发人员的个人计算机)中运行时,我们希望针对内存数据库运行集成测试,因为这会缩短反馈循环。 此更改的唯一缺点是,我们不能100%确保我们的代码在生产环境中能正常工作,因为它使用的是真实的数据库。
但是,此更改的好处胜于缺点,因为我们仍然可以(也应该)对真实数据库运行集成测试。 这样做的一个好方法是配置CI服务器以运行这些测试。
当然,这是一个非常简单(也许有些天真)的例子,而且我们经常遇到的情况要复杂得多。 这就是为什么我们应该遵循以下准则:
如有疑问,请省略测试配置。
规则3:我们不能编写事务集成测试
我们可能犯的最危险的错误之一是在集成测试中修改应用程序的事务行为。
如果我们使测试成为事务性的,则将忽略应用程序的事务边界,并确保在事务内部执行测试的代码。 这是非常有害的,因为它仅帮助我们隐藏可能的错误,而不是揭示它们。
如果您想知道事务性测试如何破坏测试套件的可靠性,则应阅读博客文章: Spring陷阱: Tomasz Nurkiewicz 认为有害的事务性测试 。 它提供了许多有关编写事务集成测试时隐藏的错误的有用示例。
我们必须再次问自己一个问题:
当我们使用生产环境中使用的配置时,我们是否要测试数据访问代码是否正常工作?还是只希望测试通过?
再一次,答案很明显。
摘要
这篇博客文章教导了使用三件事:
- 我们的目标不是在运行测试时验证我们的数据访问代码是否正常运行。 我们的目标是确保将我们的应用程序部署到生产环境后,它可以正常工作。
- 每个测试特定的更改都会在我们的测试配置和生产配置之间造成差异。 如果相差太大,则我们的测试是无用的。
- 事务集成测试是有害的,因为它们会忽略我们应用程序的事务行为,并隐藏错误而不是揭示错误。
这是一个很好的总结。 我们确实确实学过那些东西,但是我们也学到了更重要的东西。 我们从此博客文章中学到的最重要的事情是这个问题:
当我们使用生产环境中使用的配置时,我们是否要测试数据访问代码是否正常工作?还是只希望测试通过?
如果我们继续问这个问题,剩下的对我们来说应该是显而易见的。