当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《使用C#和RhinoMocks进行测试驱动开发的最佳实践》经验,为你挑选了3个好方法。

为了帮助我的团队编写可测试的代码,我提出了这个简单的最佳实践列表,以使我们的C#代码库更易于测试.(有些观点指的是Rhino Mocks的限制,这是C#的模拟框架,但规则也可能更普遍适用.)有没有人有他们遵循的最佳实践?

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

    首先编写测试,然后编写代码.原因:这可确保您编写可测试代码,并确保每行代码都为其编写测试.

    使用依赖注入设计类.原因:你无法模拟或测试无法看到的东西.

    使用Model-View-Controller或Model-View-Presenter将UI代码与其行为分开.原因:允许在无法测试的部分(UI)最小化的同时测试业务逻辑.

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

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

    隔离外部依赖项.原因:无法测试未解析的外部依赖项.

    将您想要模拟的方法标记为虚拟.原因:Rhino Mocks无法模拟非虚方法.

aridlehoover.. 58

绝对是一个很好的清单.以下是一些想法:

首先编写测试,然后编写代码.

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

使用依赖注入设计类.

同意.当对象创建自己的依赖项时,您无法控制它们.控制/依赖注入的反转为您提供了控制,允许您使用模拟/存根/等隔离测试对象.这是您单独测试对象的方法.

使用Model-View-Controller或Model-View-Presenter将UI代码与其行为分开.

同意.请注意,即使是演示者/控制器也可以使用DI/IoC进行测试,方法是将其作为存根/模拟视图和模型.有关更多信息,请查看Presenter First TDD.

不要编写静态方法或类.

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

编程关闭接口,而不是类.

我同意,但原因略有不同.接口为软件开发人员提供了极大的灵活性 - 除了支持各种模拟对象框架之外.例如,没有接口就无法正确支持DI.

隔离外部依赖项.

同意.使用接口隐藏您自己的外观或适配器(视情况而定)后面的外部依赖项.这将允许您将软件与外部依赖关系隔离,无论是Web服务,队列,数据库还是其他内容.当您的团队无法控制依赖关系(即外部)时,这一点尤为重要.

将您想要模拟的方法标记为虚拟.

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

并且,需要考虑几个新点:

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

使用Bill Wake的Arrange/Act/Assert技术编写测试.这种技术非常清楚地说明了必要的配置,实际测试的内容以及预期的内容.

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

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

实施持续集成.在每个"绿色栏"上签入您的代码.构建您的软件并在每次办理登机手续时运行全套单元测试.(当然,这本身并不是编码实践;但它是保持软件清洁和完全集成的一个令人难以置信的工具.)



1> aridlehoover..:

绝对是一个很好的清单.以下是一些想法:

首先编写测试,然后编写代码.

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

使用依赖注入设计类.

同意.当对象创建自己的依赖项时,您无法控制它们.控制/依赖注入的反转为您提供了控制,允许您使用模拟/存根/等隔离测试对象.这是您单独测试对象的方法.

使用Model-View-Controller或Model-View-Presenter将UI代码与其行为分开.

同意.请注意,即使是演示者/控制器也可以使用DI/IoC进行测试,方法是将其作为存根/模拟视图和模型.有关更多信息,请查看Presenter First TDD.

不要编写静态方法或类.

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

编程关闭接口,而不是类.

我同意,但原因略有不同.接口为软件开发人员提供了极大的灵活性 - 除了支持各种模拟对象框架之外.例如,没有接口就无法正确支持DI.

隔离外部依赖项.

同意.使用接口隐藏您自己的外观或适配器(视情况而定)后面的外部依赖项.这将允许您将软件与外部依赖关系隔离,无论是Web服务,队列,数据库还是其他内容.当您的团队无法控制依赖关系(即外部)时,这一点尤为重要.

将您想要模拟的方法标记为虚拟.

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

并且,需要考虑几个新点:

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

使用Bill Wake的Arrange/Act/Assert技术编写测试.这种技术非常清楚地说明了必要的配置,实际测试的内容以及预期的内容.

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

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

实施持续集成.在每个"绿色栏"上签入您的代码.构建您的软件并在每次办理登机手续时运行全套单元测试.(当然,这本身并不是编码实践;但它是保持软件清洁和完全集成的一个令人难以置信的工具.)


我经常发现,如果一个测试难以阅读,那不是框架的错,而是它测试的代码的错误.如果SUT设置起来很复杂,那么可能应该分解为更多概念.

2> zadam..:

如果您正在使用.Net 3.5,您可能需要查看Moq模拟库 - 它使用表达式树和lambdas来删除大多数其他模拟库的非直观记录 - 回复习惯用法.

查看此快速入门,了解您的测试用例变得多么直观,这是一个简单的示例:

// ShouldExpectMethodCallWithVariable
int value = 5;
var mock = new Mock();

mock.Expect(x => x.Duplicate(value)).Returns(() => value * 2);

Assert.AreEqual(value * 2, mock.Object.Duplicate(value));


我认为新版本的Rhino Mocks也是这样的

3> Hamish Smith..:

了解假货,模拟和存根之间的区别以及何时使用它们.

避免过度使用模拟指定交互.这使得测试变得脆弱.

推荐阅读
罗文彬2502852027
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有