c# - 使用 C# 和 RhinoMocks 进行测试驱动开发的最佳实践

标签 c# unit-testing tdd rhino-mocks

<分区>

为了帮助我的团队编写可测试的代码,我提出了这个简单的最佳实践列表,以提高我们的 C# 代码库的可测试性。 (其中一些要点涉及 Rhino Mocks 的局限性,Rhino Mocks 是 C# 的模拟框架,但这些规则也可能适用于更普遍的情况。)有人有他们遵循的最佳实践吗?

为了最大限度地提高代码的可测试性,请遵循以下规则:

  1. 先写测试,再写代码。原因:这确保您编写可测试的代码,并确保每一行代码都为它编写测试。

  2. 使用依赖注入(inject)设计类。原因:您不能模拟或测试看不到的东西。

  3. 使用 Model-View-Controller 或 Model-View-Presenter 将 UI 代码与其行为分开。原因:允许测试业务逻辑,而无法测试的部分(用户界面)已最小化。

  4. 不要编写静态方法或类。原因:静态方法很难或不可能隔离,Rhino Mocks 无法模拟它们。

  5. 基于接口(interface)而不是类进行编程。原因:使用接口(interface)阐明了对象之间的关系。接口(interface)应该定义对象从其环境中需要的服务。此外,可以使用 Rhino Mocks 和其他模拟框架轻松模拟接口(interface)。

  6. 隔离外部依赖。原因: Unresolved external 依赖无法测试。

  7. 将您打算模拟的方法标记为虚拟。原因:Rhino Mocks 无法模拟非虚拟方法。

最佳答案

绝对是一个不错的列表。这里有一些想法:

Write the test first, then the code.

我同意,在高层次上。但是,我会更具体:“先编写测试,然后编写足够代码以通过测试,然后重复。”否则,我担心我的单元测试看起来更像是集成或验收测试。

Design classes using dependency injection.

同意。当对象创建自己的依赖项时,您无法控制它们。控制反转/依赖注入(inject)为您提供了控制权,允许您使用模拟/ stub /等隔离被测对象。这就是您隔离测试对象的方式。

Separate UI code from its behavior using Model-View-Controller or Model-View-Presenter.

同意。请注意,即使是演示者/ Controller 也可以使用 DI/IoC 进行测试,方法是将其交给 stub /模拟 View 和模型。查看Presenter First TDD 了解更多信息。

Do not write static methods or classes.

不确定我是否同意这一点。可以在不使用模拟的情况下对静态方法/类进行单元测试。所以,也许这是您提到的 Rhino Mock 特定规则之一。

Program off interfaces, not classes.

我同意,但原因略有不同。接口(interface)为软件开发人员提供了很大的灵 active ——不仅仅是对各种模拟对象框架的支持。例如,没有接口(interface)就无法正确支持 DI。

Isolate external dependencies.

同意。使用接口(interface)将外部依赖项隐藏在您自己的外观或适配器(视情况而定)之后。这将允许您将软件与外部依赖隔离开来,无论是 Web 服务、队列、数据库还是其他东西。当您的团队无法控制依赖性(也就是外部)时,这一点尤其很重要。

Mark as virtual the methods you intend to mock.

这是 Rhino Mocks 的限制。在一个更喜欢手工编码 stub 而不是模拟对象框架的环境中,这是没有必要的。

还有一些新的要点需要考虑:

使用创 build 计模式。这将有助于 DI,但它也允许您隔离该代码并独立于其他逻辑对其进行测试。

使用 Bill Wake's Arrange/Act/Assert technique 编写测试. 这种技术非常清楚什么配置是必要的,实际测试的是什么,以及预期的是什么。

不要害怕推出自己的模拟/ stub 。通常,您会发现使用模拟对象框架会使您的测试难以阅读。通过滚动你自己的,你将完全控制你的模拟/ stub ,并且你将能够保持你的测试可读。 (引用上一点。)

避免将单元测试中的重复重构为抽象基类或设置/拆卸方法的诱惑。这样做会隐藏配置/清理代码,以免开发人员试图理解单元测试.在这种情况下,每个单独测试的清晰度比重构重复更重要。

实现持续集成。在每个“绿色条”上 checkin 您的代码。构建您的软件并在每次 checkin 时运行全套单元测试。 (当然,这本身并不是一种编码实践;但它是一种令人难以置信的工具,可以让您的软件保持清洁和完全集成。)

关于c# - 使用 C# 和 RhinoMocks 进行测试驱动开发的最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/124210/

相关文章:

unit-testing - 当测试在另一个包中时获取覆盖率统计信息

unit-testing - 构建软件时使用的兼容性测试和其他测试方法

android - 我可以在 Android 开发过程中使用 TDD 吗?

c# - 当类相互依赖或外部数据时如何使用单元测试?

c# - 在文件阅读单词生成器上进行 TDD 的正确方法

c# - 在 WCF 中使用 [DataContract] 而不是 [Serializable] 有什么优势

c# - 从 jQuery 对话框按钮事件中单击 ASP.NET 按钮

c# - 从菜单中做出决定

java - Robolectric 未正确处理 getApplicationContext() - NPE

c# - 使用空对象初始值设定项有什么缺点吗?