java - 在 JUnit 中设置测试的成本——在遗留代码中使用模拟对象与存储库测试
问题描述
我从事一个已经存在多年的项目。通过所有测试构建项目所需的时间几乎是耸人听闻的(不是很好)。这主要是由于有很多模块,以及大量的单元测试,它们使用存储库来设置测试数据,而不是模拟所需的行为。使用存储库的单元测试会花费大量时间进行测试设置,而且运行速度非常慢。由于系统非常大,这会增加很多时间。
我们通过使用 Mockito 来模拟存储库来编写所有新的单元测试(除非我们显然是在实际测试存储库)。只要我们有时间和机会,我们还会尝试将所有现有的单元测试重写为使用存储库的模拟而不是实际的存储库。完全消除在我们的测试中使用 repo 对运行测试所需的时间有很大的影响。
许多遗留代码通过使用构建器和测试实用程序来设置其测试数据,而这些构建器和测试实用程序又使用存储库。由于域非常复杂,这通常涉及设置大量对象以及它们如何相互关联。因此,将一类测试(比如大约 15 个测试)重写为仅使用模拟对象可能非常耗时。和其他地方一样,时间不是无限的资源。
如果我们正在向一个类添加一些新功能,那么只编写一个新的存储库测试(除了现有的 15 个)要比通过使用不同的模拟对象准确地找出需要如何设置测试数据要容易得多.
我试图找到一些关于测试设置如何以及在多大程度上影响运行测试的实际时间的信息,但我没有找到任何有用的信息。我唯一的“事实”是我在运行测试课程时所做的观察。repo 测试的测试设置可能很容易花费大约 10 秒,而模拟测试类的测试设置则在不到一秒的时间内开始。
注意:我知道我可以使用 JUnit Stopwatch 对单个或一组测试进行基准测试,但我的问题更关心的是最佳实践,而不是运行测试需要多长时间。
我有两个问题:
假设我遇到一个测试类,它已经有 15 个单元测试,其中没有一个模拟任何行为。我写了一个测试并在课堂上做了一个小修复。我没有时间重新编写整个测试类来模拟对象。我是否应该只添加一个新测试而不模拟任何行为并遵循现有的(和坏的)模式?我是否有 15 个非模拟测试和 1 个模拟测试或者我是否有 16 个非模拟测试真的很重要吗?
在我的包含 15 个单元测试的测试类中,一些测试比其他测试更容易重构。只重写五个测试以使用模拟对象是否值得?有一个测试类,其中一些测试使用模拟而另一些不使用,这是违反最佳实践还是以任何其他方式不好?
解决方案
正如@ShanuGupta 所写,您的问题没有一般性的答案。
但这是我的想法:
在正确性之后,可读性是代码的第二大期望值,尤其是测试代码(因为它是可执行规范)
另一方面,没有规定一个单元不能有多个测试类。因此,我会将不使用模拟的“旧”测试方法与“模拟”测试分开,方法是将它们放在单独的测试类中。
推荐阅读
- javascript - 推送到数组时,值被重复
- python - VS Code 在 Docker 容器中远程调试 Python
- spring - Spring批处理JpaPagingItemReader页面大小和maxitemcount
- node.js - windows的电子自动更新
- mysql - 在 MySQL 数据库中,您如何为属性提供条件
- c++ - 逐位复制图像 C++
- sql-server - Varchar charset=utf8 vs nvarchar
- facebook-graph-api - Facebook Graph API 发布到组失败与 prod 应用程序,但在测试应用程序中工作
- reactjs - 创建具有依赖项的 NPM 包仅用于示例
- machine-learning - LSTM 不会只输出一个数字而不是数字向量