gpt4 book ai didi

Java 单元测试 - 适当的隔离?

转载 作者:搜寻专家 更新时间:2023-11-01 01:37:49 26 4
gpt4 key购买 nike

我想知道我的单元测试方法是否错误:

我的应用程序有一个 Bootstrap 进程,它初始化多个组件并向各种子系统提供服务——我们称之为“ Controller ”。

在许多情况下,为了对这些子系统进行单元测试,我需要访问 Controller ,因为这些子系统可能依赖于它。我进行此单元测试的方法是初始化系统,然后将 Controller 提供给任何需要它的单元测试。我通过继承实现了这一点:我有一个基本单元测试来初始化和测试 Controller ,然后任何需要 Controller 的单元测试都会扩展这个基类,因此可以访问它。

我的问题是这样的:

(1) 这是否实现了适当的隔离?对我来说,单元测试应该单独进行,以便它们是可重复和独立的——我提供一个真正的初始化 Controller 而不是模拟它或试图模拟每个测试所需的特定环境是否可以?

(2) 作为最佳实践(假设我以前的方法没问题) - 我应该为每个单元测试一遍又一遍地创建 Controller ,还是只创建一次就足够了(它的状态没有改变)。

最佳答案

如果我们提供一个“真正的” Controller 来测试另一个组件,那么严格来说,我们正在执行集成测试而不是单元测试。这不一定是坏事,但请考虑以下几点:

创建 Controller 的成本

如果 Controller 是一个重量级的对象,构建成本相当高,那么每个单元测试都会产生这个成本。随着单元测试数量的增加,该成本可能开始主导整个测试执行时间。总是希望保持单元测试的运行时间尽可能小,以便在代码更改后快速周转。

Controller 依赖

如果 Controller 是一个复杂的对象,它可能有自己的依赖关系,需要实例化才能构造 Controller 本身。例如,它可能需要访问某种数据库或配置文件。现在,不仅需要初始化 Controller ,还需要初始化那些组件。随着应用程序随着时间的推移而发展, Controller 可能需要越来越多的依赖项,随着时间的推移只会使这个问题变得更糟。

Controller 状态

如果 Controller 携带任何状态,则单元测试的执行可能会改变该状态。反过来,这可能会改变后续单元测试的行为。此类更改可能会导致单元测试的明显不确定行为,从而引入掩盖错误的可能性。解决这个问题的方法是为每个测试重新创建 Controller ,如果创建成本很高(如上所述),这可能是不切实际的。

组合问题

被测单元和 Controller 对象的复合系统的可能输入组合的数量可能比单独的单元的组合数量大得多。这个数字可能太大而无法实际测试。通过使用 stub 或模拟对象代替 Controller 单独测试单元,更容易控制组合的数量。

上帝对象

如果在每个单元测试中所有组件都可以方便地访问 Controller ,那么将 Controller 变成一个知道系统中每个组件的一切的 God Object 将是一个很大的诱惑。更糟糕的是,这些组件可能会开始通过该上帝对象相互交互。最终结果是应用程序组件之间的分离开始受到侵 eclipse ,系统开始变得单一。

技术债务

即使 Controller 在今天是无状态的并且实例化成本很低,但随着应用程序的发展,这种情况可能会发生变化。如果那一天是在我们编写了大量单元测试之后到来的,我们可能会面临所有这些测试的大规模重构练习。此外,实际的系统代码可能还需要重构以将所有 Controller 引用替换为更轻量级的接口(interface)。重构成本可能很高——甚至可能太高而无法考虑,从而导致系统“卡”在不希望的形式中。

推荐

为了在现在和将来避免这些陷阱,我的建议是避免将真实 Controller 提供给单元测试。

完整的 Controller 可能很难有效地 stub 或模拟。这将引发(理想的)压力,将组件的依赖关系表达为“薄”、集中的界面,而不是 Controller 可能呈现的“厚”、“厨房水槽”界面。为什么这是可取的?这是可取的,因为这种做法促进了系统组件之间更好的关注点分离,产生了远远超出单元测试代码库的架构优势。

有关如何实现关注点分离和通常编写可测试代码的大量实用建议,请参阅 Misko Hevery 的 guidetalks

关于Java 单元测试 - 适当的隔离?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7238105/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com