本文介绍了如何有效地单元测试使用ADO.NET和SQL Server与NUnit的DAL?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



这是伟大的stubbing / mocking的存储库,它被使用的地方,当进行单元测试时,我爱它!



但是,我想为DAL本身添加一些单元测试。最好使用Rhino Mocks和NUnit。然而,如果一个坚实的案例可以做出犀牛不能解决这个问题,我可以转向MoQ。



我不想在单元测试期间与任何数据库进行通信,以保持它们更纯粹,同时仍然有效地测试DAL本身。然而,如果你不能真正有效地单元测试一个DAL本身没有它与数据库,与内存替换或基于可移植文件的替代,将与SQL Server兼容的同样的SqlConnection和SqlCommand调用的替代品。



打开以重构DAL,如果需要,使它更容易注入,只要它不会使设计同时复杂化。

解决方案

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



我没有使用ADO。 NET很多,但我想这个NHibernate的例子足够了:

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

当然,假设代码写得正确,依赖关系( sessionFactory 即)将通过接口传递,因此容易存根,因此写单元测试是可能的(你只需要嘲笑许多东西,使它发生)。



Purist方法将是写这样的单元测试,因为它是另一个数据点,证明你的代码确实做你所假设的(调用 Get )。但是,请注意,这样的测试是相当昂贵的,因为你必须stub整个数据库访问由您的提供者(嘲笑 sessionFactory 返回mocked会话,然后检查呼叫



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



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

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




  • 很慢

  • 它有几个可能的失败点难以控制(ORM配置,内存数据库设置,可能无效的测试数据)

  • 给你错误的做集成测试的感觉(而你不是;内存数据库可能表现完全不同于您的真实生产环境)



除非可以将完全相同的数据库加载到内存, (这将是DAL测试优先级)与孤立的单元测试备份(只要你能负担得起写)。


So you have a DAL in C# that using the Repository pattern and you have an interface for each Repository. It is backed by ADO.NET, MS SQL Server, and Stored Procedure calls.

This is great for stubbing/mocking out the repository where it is being used else where when doing unit tests, and I Love it!

However, I would love to add some unit testing for the DAL itself. Preferably using Rhino Mocks with NUnit. However I am open to switching to MoQ if a solid case could be made that it can do something that Rhino can't in relation to this question.

I would rather not have it talk to any DB during the Unit Tests to keep they more "pure" while still effectively testing the DAL itself. If however you can not really effectively unit test a DAL itself without it talking to a DB, what would be the alternatives that could be in memory replacements or a portable file based replacements that are compatible with of SQL Server and same SqlConnection and SqlCommand calls.

Open to refactoring the DAL if needed to make it easier to inject as long as it doesn't over complicate the design at the same time. Already using Microsoft Unity, for DI with the Repository Pattern.

解决方案

What exactly would those unit tests test? Considering typical DAL code is rarely anything more than delegating actual work to 3rd party data access code (ADO.NET, EntityFramework, NHibernate).

I haven't used ADO.NET much, but I suppose this NHibernate example is sufficient enough:

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

Of course, assuming the code is wrote correctly, all the dependencies (sessionFactory namely) would be passed via interfaces and therefore easy to stub, so writing unit test is possible (you'll just have to mock a lot of stuff to make it happen).

Purist approach would be to write such unit test, as it's yet another data point proving your code indeed does what you assume (calling Get). However, note that test like this is rather expensive, as you essentially have to stub entire database access made by your provider (mocking sessionFactory to return mocked session which is then checked for calls made).

This is difficult decision to be made (whether follow purist approach in this case), as you will have to write integration tests with real database anyways. And those tests will cover exactly the same areas as unit tests you'd wrote, but working in real environment (instead of stubbed one).

In my experience, unit testing DAL is usually not worth the benefits it offers, especially when contrasted with its rather high costs (time spent writing code to stub the database environment) for unit test) and existence of proper integration tests suite.

And last, I would advise against using in-memory database in any kind of testing. For the reasons below:

  • it is slow
  • it has several possible failure points that may be difficult to control (ORM configuration, in-memory database setup, possibly invalid test data)
  • gives you false sense of doing integration testing (while you're not; in-memory database might behave entirely different than your real, production one)

Unless you can load up exactly the same database to the memory, stick to proper integration tests (that would be DAL testing priority) with isolated unit tests backup (only if you can afford to write them).

这篇关于如何有效地单元测试使用ADO.NET和SQL Server与NUnit的DAL?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 10:41