上面的代码演示了, 我们用Action委托实现另一个方法包装一下目标方法使其在TransactionScope块中.
  我们还可以使用xUnit 类库 这实现同样的操作, 这里使用是xUnit 1.8版本. 还有MbUnit,NUnit的[RollBack]特性与这个类似. 如果您还不熟悉怎么使用xUnit请先看这里介绍. 下面的代码使用 xUnit 代码变得更加简洁:
1:      /// <summary>
2:      /// Database unit testing with xUnit demo
3:      /// </summary>
4:      /// <remarks>http://wintersun.cnblogs.com </remarks>
5:      public class TestDbWithxUnit
6:      {
7:          [Fact]
8:          [AutoRollback]
9:          public void Test_Add_One_Enity()
10:          {
11:              //arrange
12:              var employee = this.CreateNewEmployee();
13:              var employRepository = RepositoryHelper.GetEmployeeRepository();
14:
15:              //act
16:              employRepository.Add(employee);
17:              employRepository.Save();
18:
19:              //assert
20:              var employeelist =
21:                 employRepository.Repository.Find(e => e.EmployeeID == employee.EmployeeID);
22:              Assert.NotNull(employeelist);
23:              Assert.Equal(new List<Employee> { employee }, employeelist.ToList());
24:          }
25:  }
  上面的代码我们只需在方法上加一个AutoRollback的Attribute可以了, 注意你先需要引用xunit.extensions.dll
  当然,标准的单元测试我们完全隔离数据库, 数据访问组件在单元测试中不应该访问数据库. 我们使用Mock框架来实现对数据库的隔离, 如下代码演示了我们使用Moqv4.0.20926 和 xUnit 来实现的单元测试:
1:          [Fact]
2:          public void TestWithMoq()
3:          {
4:              //arrange
5:              var mock = new Mock<IRepository<Employee>>();
6:              Employee employee = this.CreateNewEmployee();
7:              var list = new List<Employee>() { employee };
8:
9:              mock.Setup(ep => ep.Add(It.IsAny<Employee>()))
10:                  .Callback(()=>Console.WriteLine("Add()"));
11:              mock.Setup(ep => ep.Find(It.IsAny<Expression<Func<Employee, bool>>>()))
12:                  .Returns(list);
13:              mock.Setup(ep => ep.Save())
14:               .Callback(() => Console.WriteLine("Save()"));
15:              var employeeRespository = mock.Object;
16:
17:              //act
18:              employeeRespository.Add(employee);
19:              employeeRespository.Save();
20:
21:              //verify method
22:              mock.Verify(ep => ep.Add(It.IsAny<Employee>()));
23:              mock.Verify(ep => ep.Save());
24:
25:              //assert
26:              var employeelist =
27:                employeeRespository.Find(e => e.EmployeeID == employee.EmployeeID);
28:              Assert.NotNull(employeelist);
29:              Assert.Equal(new List<Employee> { employee }, employeelist.ToList());
30:          }
  Employee是实体类, IRepository<T>是一个统一数据访问interface, 实现martinfowler的Repository模式;  上面的代码Mock了其中的Add,Save方法, 在调用后并做了Verify,确认之前Mock的方法有被调用到,  后的部分才是Assert语句块. 代码很简单.
  除了使用Mock框架, 我们还可以使用依赖注入容器来注入一个具体的Fake对象实现对访问数据库的隔离, 我们使用Unity 2.1 来实现:
1:          [Fact]
2:          public void TestWithDIContainer()
3:          {
4:              //arrange
5:              var employee = this.CreateNewEmployee();
6:              var list = new List<Employee>() { employee };
7:              var employeeRespository = GetRepositoryInstance("for testing");
8:
9:              //act
10:              employeeRespository.Add(employee);
11:              employeeRespository.Save();
12:
13:              //assert
14:              var employeelist =
15:                employeeRespository.Find(e => e.EmployeeID == employee.EmployeeID);
16:              Assert.NotNull(employeelist);
17:              Assert.Equal(new List<Employee> { employee }, employeelist.ToList());
18:          }
19:
20:          private IRepository<Employee> GetRepositoryInstance(string name)
21:          {
22:              //Initial container
23:              var container = new UnityContainer();
24:              container.RegisterType<IRepository<Employee>, EFRepository<Employee>>();
25:              container.RegisterType<IRepository<Employee>, FakeRepository<Employee>>("for testing");
26:              //....
27:              return container.Resolve<IRepository<Employee>>(name);
28:          }
  上面的代码为了演示的简便, 我们实现创建容器注册对象在一个private方法中; 您也可以使用其它IOC/DI的容器. FakeRepository<Employee>是一个实现了IRepository<T>的具体类, 在其内部可以在内存中操作实体,或是其它方式. 具体看您的需求了.
  以上所有是我们介绍对数据访问层或数据库进行单元测试的解决方法:
  1. 使用TransactionScope类实现测试方法回滚
  2. 使用xUnit类库的AutoRollback特性实现自动回滚
  3. 使用Moq框架来实现隔离数据库的访问
  4. 使用Unity容器注入Fake对象来实现隔离数据库的访问