传统nUnit测试示例
  好了,背景已经足够了。让我们来针对这部分功能进行测试。喂,等等,我们……现在有功能吗?有!我测试的描述是,
  当从构造器链构造考试类时,三个属性应该要赋相应的值。
  是的,足够简单使我们一目了然,也足够复杂,我们需要用测试来保障它的功能。 1. 保证它被运行---覆盖测试;2. 保证它是按我的设计进行的---行为测试。
  看代码:
[TestFixture]
public class when_create_an_exam
{
[Test]
public void it_should_assign_parameters_to_properties()
{
//Arrange
var stub_exam_def = new ExamDef("98");
var stub_district = new District("01");
var stub_date = new Date(2011, 1, 1);
//Action
var subject = new Exam(stub_district, stub_exam_def, stub_date);
//Assert
Assert.AreEqual(stub_district,subject.District);
Assert.AreEqual(stub_exam_def,subject.ExamDef);
Assert.AreEqual(stub_date,subject.Date);
}
}
  引入三个中间变量和另外三个类的定义我不在这罗嗦了。我的命名方式也曾为人病诟,也不在这辩解。只看实质内容:分别创建三个类的实例,用于测试,至于这三个类的具体内容,我其实并不关心。所以用个词Stub来表示我的不关心。DDD的核心理念之一:名符其实。后,我的断言只判断属性的值是否与构造器传入值相符。OK,完成!
  坏味道?---重构的提出
  过一段时,间。我们再回头看看这段测试,会有些小小的不舒服。特别,我们还有更多的类有类似的构造器赋值功能,还有更多更复杂的功能等着我们去测试,我们在做商业软件,不是吗?随着类似的测试更得越多。这些小小的不舒服会越积越大。
  这面的测试有什么问题?
  1. 测试有三部分:建立测试环境;调用被测功能,(测试的本体);断言。上面的代码,我甚至都已经刻意用注释分离出了这么三块,但仍不是语法级别的分离。
  2. 对第三方的类依赖较为严重,这是本文的重点---单元测试单元化。对Exam类来说ExamDef, District都是插足的第三者。
  3. 测试代码太多,被测的实际上只有三行,虽然这不是原则性的问题,但是本着更好,更快,更强的精神,这个问题也是值得解决的。
  好了,你提出的问题已经太多了,我没办法一下子解决。3个还多?是的,我们的口号是“只要一个好”。
  MSpec的引入--- AAA语法
  言归正传,让我们本着选代和重构的原则来把这些问题一个一个解决。是的,测试也需要重构,测试代码还有bug呢?一点不奇怪。你没碰到过?噢,因为你根本不写测试代码。
  关于测试的三段式,我曾经看过有人确实在nUnit的框架下一步一步重构,形成良好了测试框架。这里我不这么麻烦了,直接上工具MSpec!测试的三段式,有个说法,叫AAA语法,分别是Arrange,Action,Assert。3A级语法,多酷!
  而MSpec用了自己的名词,分别是Establish, Because, It。看看下面改造之后的测试代码清楚什么意思了。
  看代码:
public class When_create_an_exam_by
{
private Establish context =
() =>
{
stub_exam_def = new ExamDef("98");
stub_district = new District("01");
stub_date = new Date(2011, 1, 1);
};
private Because of =
() => subject = new Exam(stub_district, stub_exam_def, stub_date);
private It should_assign_to_properties =
() =>
{
subject.District.ShouldEqual(stub_district);
subject.ExamDef.ShouldEqual(stub_exam_def);
subject.Date.ShouldEqual(stub_date);
};
private static ExamDef stub_exam_def;
private static District stub_district;
private static Date stub_date;
private static Exam subject;
}
  再看一看测试运行的结果,明了代码即文档的含义了。
  看截图:

  从nUnit升级到MSpec,给人一种耳目一新的感觉。开始也许会有些不习惯。但是,一旦习惯之后再也不想回头了。