转贴于:http://blog.csdn.net/cpcpc/article/details/6186200
单元测试需要对数据库执行CRUD(Create,Retrieve,Update,Delete)操作时,测试过后会在我们的数据库中留下大量重复的垃圾数据,这些垃圾很碍眼不是吗?而且我们的下一个测试有可能因为这些垃圾产生一些错误。
那么我们要如何处理这些垃圾数据和保证测试的稳定的呢?显然,我们需要在每次测试之前和测试完成之后让数据库都保持相同的状态。换句话说,就是我们需要"undo"这些在测试中对数据库执行的CRUD操作。
对于我们需要的这种"undo"操作,你以前是怎么做的呢?手动的移除还是使用ADO.NET的事物处理呢?这些方法都可行,但对我们来说还不够好。因为它们都需要我们编写更多的代码,影响我们的开发效率。
现在,就要开始说本文的重点了,利用COM+的自动事务处理功能来帮助我们实现我们的"undo"。
首先,写一个基类,此类能够在每一个方法完成后自动回滚对数据库的操作:
- using NUnit.Framework;
- using System.EnterpriseServices;
- [TestFixture]
- [Transaction(TransactionOption.Required)]
- public class DatabaseFixture : ServicedComponent
- {
- [TearDown]
- public void TransactionTearDown()
- {
- if (ContextUtil.IsInTransaction)
- {
- ContextUtil.SetAbort();
- }
- }
- }
下面再写一个使用此基类的示例程序:
- using NUnit.Framework;
- using System.EnterpriseServices;
- using System.Data.SqlClient;
- using System.Data;
- public class CategoryTests : DatabaseFixture
- {
- string CONN = @"Data source=localhost;user id=sa;password=sa;database=test";
- [Test]
- public void InsertTest()
- {
- for (int i = 0; i < 100; i++)
- {
- Guid guid = Guid.NewGuid();
- int value = 1;
- Guid categoryName = Insert(guid, value);
- VerifyRowExists(categoryName, true);
- }
- }
- [Test]
- public void DeleteTest()
- {
- for (int i = 0; i < 100; i++)
- {
- Guid guid = Guid.NewGuid();
- int value = 1;
- Guid categoryName = Insert(guid, value);
- Delete(categoryName);
- VerifyRowExists(categoryName, false);
- }
- }
- /**/
- /// <summary>
- /// 新增一条记录
- /// </summary>
- /// <param name="categoryName"></param>
- /// <returns></returns>
- private Guid Insert(Guid DigitID,int value)
- {
- using (SqlConnection conn = new SqlConnection(CONN))
- {
- string strSQL = "Insert digits (DigitID,Value) values('" + DigitID + "','" + value + "')";
- SqlCommand cmd = new SqlCommand(strSQL, conn);
- conn.Open();
- cmd.ExecuteNonQuery();
- }
- return DigitID;
- }
- /**/
- /// <summary>
- /// 删除一条记录
- /// </summary>
- /// <param name="categoryName"></param>
- /// <returns></returns>
- private Guid Delete(Guid DigitID)
- {
- using (SqlConnection conn = new SqlConnection(CONN))
- {
- string strSQL = "Delete from digits Where DigitID='" + DigitID + "'";
- SqlCommand cmd = new SqlCommand(strSQL, conn);
- conn.Open();
- cmd.ExecuteNonQuery();
- }
- return DigitID;
- }
- /**/
- /// <summary>
- /// 对执行的数据库操作进行验证
- /// </summary>
- /// <param name="categoryName"></param>
- /// <param name="shouldExist"></param>
- private void VerifyRowExists(Guid DigitID, bool shouldExist)
- {
- SqlConnection conn = new SqlConnection(CONN);
- conn.Open();
- string strSQL = "Select * from Digits where DigitID='" + DigitID + "'";
- SqlCommand cmd = new SqlCommand(strSQL, conn);
- SqlDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
- Assert.AreEqual(shouldExist, dr.HasRows);
- dr.Close();
- }
- }
如果编译上面的程序,还需要给程序加一个强名称,否则是无法通过的
在命令行使用 sn -k test.snk
然后把 test.snk 拷贝到程序目录中,再设置
[assembly: AssemblyKeyFile(@"../../../test.snk")]