5

因此,您在 C# 中有一个使用存储库模式的 DAL,并且每个存储库都有一个接口。它由 ADO.NET、MS SQL Server 和存储过程调用提供支持。

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

但是,我很想为 DAL 本身添加一些单元测试。最好使用带有 NUnit 的 Rhino Mocks。但是,如果可以证明它可以做一些 Rhino 在这个问题上不能做的事情,我愿意切换到 MoQ。

我宁愿在单元测试期间不让它与任何数据库对话,以保持它们更“纯”,同时仍然有效地测试 DAL 本身。但是,如果您不能真正有效地对 DAL 本身进行单元测试而不与数据库通信,那么在内存替换或基于可移植文件的替换中的替代方案是什么,这些替换与 SQL Server 以及相同的 SqlConnection 和 SqlCommand 调用兼容。

如果需要,可以重构 DAL 以使其更容易注入,只要它不会同时使设计过于复杂。已经在使用 Microsoft Unity,用于具有存储库模式的 DI。

4

1 回答 1

7

这些单元测试究竟会测试什么?考虑到典型的 DAL 代码,除了将实际工作委派给第 3 方数据访问代码(ADO.NET、EntityFramework、NHibernate)之外,几乎没有什么比这更重要的了。

我没有太多使用 ADO.NET,但我想这个 NHibernate 示例就足够了:

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

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

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

这是很难做出的决定(在这种情况下是否遵循纯粹的方法),因为无论如何您都必须使用真实数据库编写集成测试。这些测试将涵盖与您编写的单元测试完全相同的领域,但在真实环境中工作(而不是存根)。

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

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

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

除非您可以将完全相同的数据库加载到内存中,否则请坚持适当的集成测试(这将是 DAL 测试的优先级)和独立的单元测试备份(只有在您有能力编写它们的情况下)。

于 2012-07-31T23:23:58.047 回答