如何有效地对使用ADO.NET和SQL Server与NUnit的DAL进行单元测试?

Rod*_*ley 5 nunit unit-testing data-access-layer mocking c#-4.0

所以你在C#中有一个使用Repository模式的DAL,你有一个每个Repository的接口.它受ADO.NET,MS SQL Server和存储过程调用的支持.

这非常适合存储/模拟使用它的存储库,否则在进行单元测试时,我喜欢它!

但是,我很乐意为DAL本身添加一些单元测试.最好使用带有NUnit的Rhino Mocks.但是,如果可以做出一个可以做Rhino无法解决的问题,那么我愿意转向MoQ.

在单元测试期间,我宁愿不让任何数据库与任何数据库通信,以保持它们更"纯粹",同时仍然有效地测试DAL本身.但是,如果没有它与数据库通信,你就无法真正有效地对DAL本身进行单元测试,那么在内存替换或基于便携式文件的替代方案中可能存在哪些替代方案,这些替换方式与SQL Server和相同的SqlConnection和SqlCommand调用兼容.

如果需要,可以重构DAL,只要它不会同时使设计复杂化,就可以更容易注入.已经使用Microsoft Unity,用于DI与存储库模式.

k.m*_*k.m 7

那些单元测试究竟会测试什么?考虑典型的DAL代码很少是将实际工作委托给第三方数据访问代码(ADO.NET,EntityFramework,NHibernate).

我没有多少使用过ADO.NET,但我认为这个NHibernate示例足够了:

public User GetUser(int id)
{
    using (var session = sessionFactory.OpenSession())
    {
        return session.Get<User>(id);
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,假设代码被正确写入,所有依赖项(sessionFactory即)都将通过接口传递,因此易于存根,因此编写单元测试是可能的(您只需要模拟很多东西来实现它) .

纯粹的方法是编写这样的单元测试,因为它是另一个数据点,证明你的代码确实做了你所假设的(调用Get).但请注意,这样的测试相当昂贵,因为您基本上必须存储由提供程序进行的整个数据库访问(模拟sessionFactory返回模拟会话,然后检查所做的调用).

这是一个很难做出的决定(在这种情况下是否遵循纯粹的方法),因为你必须编写与真实数据库的集成测试.这些测试将覆盖您编写的单元测试完全相同的区域,但在真实环境中工作(而不是在实际环境中).

根据我的经验,单元测试DAL通常不值得它提供的好处,特别是与其相当高的成本(编写代码来存根数据库环境所花费的时间)进行单元测试的对比)以及适当的集成测试套件的存在.

最后,我建议不要在任何类型的测试中使用内存数据库.原因如下:

  • 它很慢
  • 它有几个可能难以控制的故障点(ORM配置,内存数据库设置,可能是无效的测试数据)
  • 让你错误地进行集成测试(虽然你不是;内存数据库的行为可能与真实的生产数据完全不同)

除非您可以将完全相同的数据库加载到内存中,否则请坚持使用隔离的单元测试备份进行适当的集成测试(这将是DAL测试优先级)(仅当您能够负担得起它们时).