通过合同设计,编写测试友好的代码,对象构建和依赖注入将所有的最佳做法 [英] Design By Contract, writing test-friendly code, object construction and Dependency Injection putting all together best practices

查看:180
本文介绍了通过合同设计,编写测试友好的代码,对象构建和依赖注入将所有的最佳做法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直试图找出编写测试友好代码的最佳实践,但更具体地说是与对象构造相关的实践。在蓝皮书中,我们发现我们应该在创建对象时强制执行不变量,以避免我们的实体,价值对象等的腐败,设计合同似乎是避免我们对象腐败的解决方案,但是当我们遵循这一点,我们可以最终编写如下代码:

I have been trying to figure out the best practices to write test-friendly code, but more specifically the practices related to object construction. In the blue book we discovered that we should enforce invariants when creating objects to avoid the corruption of our entities, value objects, etc. with this thought in mind, Design By Contract seems like the solution to avoid the corruption of our objects, but when we follow this, we could end up writing code like this:

class Car
{
   //Constructor
   public Car(Door door, Engine engine, Wheel wheel)
   {
      Contract.Requires(door).IsNotNull("Door is required");
      Contract.Requires(engine).IsNotNull("Engine is required");
      Contract.Requires(wheel).IsNotNull("Wheel is required");
      ....
   }
   ...
   public void StartEngine()
   {
      this.engine.Start();
   }
}

这样看起来好看吗?似乎我们正在建立一个安全的类,暴露所需的合同,所以每次创建一个 Car 对象时,我们可以确定该对象是有效的。

Well this looks good at first sight right? It seems we are building a safe class exposing the contract required so every time a Car object is created we can know for sure that the object is "valid".

现在让我们从测试驱动的角度来看这个例子。

Now let's see this example from a testing-driven point of view.

我想制作测试友好的代码,但为了能够隔离测试我的 Car 对象I需要为每个依赖关系创建一个存根或虚拟对象,只是为了创建我的对象,即使我可能只想测试一个只使用这些依赖关系的方法,如 StartEngine 方法。根据Misko Hevery测试哲学,我想编写我的测试明确指出,我不在乎Door或Wheel对象,只是传递null引用到构造函数,但是由于我正在检查null,我只是不能做

I want to build test-friendly code but in order to be able to test in isolation my Car object I need to create either a mock a stub or a dummy object for each dependency just to create my object, even when perhaps I just want to test a method that only uses one of these dependencies like the StartEngine method. Following Misko Hevery philosophy of testing I'd like to write my test specifying explicitly that I do not care about the Door or Wheel objects just passing null reference to the constructor, but since I am checking for nulls, I just can't do it

这只是一小段代码,但是当您面对真正的应用程序时,写测试变得越来越难,因为您必须解决您的主题的依赖关系

This is just a small piece of code but when you are facing a real application writing tests becomes harder and harder because you have to resolve dependencies for your subject

Misko建议我们不要滥用代码中的空白检查(与合同设计相矛盾),因为这样做,写作测试变得很痛苦,作为替代,他认为这更好写出更多的测试比只是因为我们的代码是安全的,因为我们有无处不在的检查

Misko proposes that we should not abuse of null-checks in the code (which contradicts Design By Contract) because of doing it, writing tests becomes a pain, as an alternative he sais it's better to write more tests than "have just the ilussion that our code is safe just because we have null-checks everywhere"

你有什么想法?
你会怎么做?
最好的做法应该是什么?

What are your thoughts on this? How would you do it? What should be the best practice?

推荐答案

看看测试数据构建器

您可以使用预配置的数据创建构建器一次,如果需要,请覆盖属性,并调用 Build()以获取正在测试的系统的新实例。

You create the builder once with preconfigured data, override a property if neccessary and call Build() to get a new instance of your system under test.

或者您可以查看企业库的来源。测试包含一个基类,名为 ArrangeActAssert ,为BDD-ish测试提供了不错的支持。您在从AAA派生的类的安排方法中实现测试设置,每当您运行特定测试,它将被调用。

Or you can have a look at the sources of the Enterprise Library. The tests contain a base class called ArrangeActAssert that provides nice support for BDD-ish tests. You implement your test setup in the Arrange method of a class derived from AAA and it will be called whenever you run a specific test.

这篇关于通过合同设计,编写测试友好的代码,对象构建和依赖注入将所有的最佳做法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆