这里也许有人会问,如果我的项目很大,每个测试方法都需要连接数据库,在每个方法执行的时候进行连接再释放,这样是不是太耗资源太慢了,能不能在一个单元测试类实例化的时候运行一个指定的方法呢?
这是可以的。在NUnit中,我们使用[TestFixtureSetUp]和[TestFixtureTearDown]可以实现这样的功能。[TestFixtureSetUp]是指在这个测试类的整个生命周期中,它在所有的测试方法之前运行一次,而[TestFixtureTearDown]是在所有的测试方法都结束时运行。
这里要注意的,[TestFixtureSetUp]与构造函数是不一样的,它标识的方法迟于构造函数运行。我们再对这个测试类进行重构:
[TestFixture]
public class CalculatorTest
...{
private Calculator cal;
private int a, b, expected, actual;
public CalculatorTest()
...{
Console.WriteLine("执行构造函数");
}
[TestFixtureSetUp]
public void InitClass()
...{
Console.WriteLine("执行TestFixtureSetUp");
cal = new Calculator();
a = 10;
b = 2;
}
[TestFixtureTearDown]
public void FinalizeClass()
...{
Console.WriteLine("执行TestFixtureTearDown");
}
[SetUp]
public void InitMethod()
...{
Console.WriteLine("执行SetUp");
}
[TearDown]
public void FinalizeMethod()
...{
Console.WriteLine("执行TearDown");
a = 10;
b = 2;
}
[Test]
public void TestAdd()
...{
Console.WriteLine("TestAdd() Begin");
expected = 12;
actual = cal.Add(a, b);
Assert.AreEqual(expected, actual);
Console.WriteLine("TestAdd() End");
}
[Test]
public void TestMinus()
...{
Console.WriteLine("TestMinus() Begin");
expected = 8;
actual = cal.Minus(a, b);
Assert.AreEqual(expected, actual);
Console.WriteLine("TestMinus() End");
}
[Test]
public void TestMultiply()
...{
Console.WriteLine("TestMultiply() Begin");
expected = 20;
actual = cal.Multiply(a, b);
Assert.AreEqual(expected, actual);
Console.WriteLine("TestMultiply() End");
}
[Test]
public void TestDivide()
...{
Console.WriteLine("TestDivide() Begin");
expected = 5;
actual = cal.Divide(a, b);
Assert.AreEqual(expected, actual);
Console.WriteLine("TestDivide() End");
}
}
在NUnit中,我们可以很清楚地看到这个类的执行顺序:
假如我们的测试项目中有使用到数据库,可以把数据库连接写在[TestFixtureSetUp]中,把释放的代码写在[TestFixtureTearDown]中。
我相信现在大家对NUnit的这4个属性都应该有一个直观的认识了吧。都是4个很简单的属性,但是在使用中用处却是非常大的。