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

2024-05-13

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

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

不过,我很乐意为 DAL 本身添加一些单元测试。最好将 Rhino Mocks 与 NUnit 结合使用。不过,如果有充分的理由证明它可以做一些 Rhino 无法解决这个问题的事情,我愿意改用 MoQ。

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

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


那些到底是什么单元测试测试?考虑典型的 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返回模拟会话,然后检查是否进行了调用)。

这是一个很难做出的决定(在这种情况下是否遵循纯粹的方法),因为你必须写集成测试 http://en.wikipedia.org/wiki/Integration_testing无论如何,使用真实的数据库。这些测试将涵盖一模一样区域作为您编写的单元测试,但在真实环境中工作(而不是存根环境)。

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

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

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何通过 NUnit 有效地对使用 ADO.NET 和 SQL Server 的 DAL 进行单元测试? 的相关文章

随机推荐

  • 插入并发问题-多线程环境

    我有一个问题 即使用完全相同的参数在完全相同的时间调用相同的存储过程 存储过程的目的是获取记录 如果存在 或创建并获取记录 如果不存在 问题是两个线程都在检查记录是否存在并报告错误 然后都插入新记录 在数据库中创建重复记录 我尝试将操作保留
  • 钛金 Android 导航组

    您好 我是钛合金新手 它允许开发人员创建跨平台应用程序 我需要创建一个适用于 Android 和 iOS 的导航组 有没有明确的解决方案 因为 Ti UI iPhone createNavigationGrou 仅适用于 iphone 谢谢
  • Itunes Connect 测试飞行公共链接有效性

    苹果最近为试飞版本启用了公共链接功能 我们可以与任何人共享此链接 他可以使用此公共链接安装应用程序 此公共链接背后的构建有效期为 90 天 我的问题是 与用户共享公共链接后 我们可以增加构建的到期时间吗 这样公共链接的有效性就会增加 我们不
  • 将颜色映射到plotly go.饼图中的标签

    我正在使用 make subplots 和 go Pie 绘制一系列 3 个饼图 我想最终将它们放入破折号应用程序中 用户可以在其中过滤数据并且数字将更新 如何将特定颜色映射到变量 以便男性始终为蓝色 女性始终为粉红色 等等 您可以使用 c
  • 使用 Terraform 管理访问 RDS 数据库的凭据时出现问题

    我通过 Terraform 创建了一个秘密 该秘密用于访问也在 Terraform 中定义的 RDS 数据库 并且在秘密中 我不想包含username and password 因此我创建了一个空密钥 然后在 AWS 控制台中手动添加凭证
  • 在继承的ctypes.Structure类的构造函数中调用from_buffer_copy

    我有以下代码 class MyStruct ctypes Structure fields id ctypes uint perm ctypes uint 定义类后 我可以直接从缓冲区复制数据到我的字段上 例如 ms MyStruct fr
  • 一个新的 JavaScript 数组长度是否无法使用? [复制]

    这个问题在这里已经有答案了 根据MDN 文档new Array length https developer mozilla org en US docs Web JavaScript Reference Global Objects Ar
  • 将数值数据更改为分类数据 - Pandas [重复]

    这个问题在这里已经有答案了 我有一个 pandas 数据框 其中有一个数字列 金额 金额从 0 到 20000 不等 我想将其更改为定义范围的分类变量 因此 分类变量将是 0 1000 之间 1000 2000 美元之间 依此类推 直到 1
  • 多个where条件codeigniter

    如何将此查询转换为活动记录 UPDATE table user SET email email last ip last ip where username username and status status 我尝试将上面的查询转换为 d
  • JavascriptCore:在 JSExport 中将 javascript 函数作为参数传递

    JavascriptCore是iOS7中支持的新框架 我们可以使用 JSExport 协议将 objc 类的部分内容公开给 JavaScript 在javascript中 我尝试将函数作为参数传递 像这样 function getJsonC
  • dmvnorm MVN 密度 - RcppArmadillo 实现比 R 包慢,包括一些 Fortran

    The solution现已上线RCPP画廊 http gallery rcpp org articles dmvnorm arma 我从 RcppArmadillo 中的 mvtnorm 包重新实现了 dmvnorm 我有点喜欢犰狳 但我
  • docker-compose mysql 容器拒绝访问 wordpress 容器

    我遇到 mysql 5 7 容器拒绝访问 wordpress 容器的问题 我正在使用 docker compose 并且在 Mac OSX 上运行 docker Docker 应该是可用的最新版本 这是我的 docker compose y
  • Python 和 sqlite3.ProgrammingError:不允许递归使用游标

    我写了一个像这样的Python程序 它应该在多线程模式下运行 def Func host cursor db cursor execute SELECT If index Username Version Community Ip traf
  • 如何检查是否启用了更改跟踪

    我试图在运行之前确定我的数据库是否已启用更改跟踪ALTER DATABASE命令来启用它 我试图防止这些脚本多次运行时出现错误 我签到了sys databases and sys dm tran commit table但无法找到我要找的东
  • 在 React.js 中有条件地设置 html 属性

    我在为 React 中的单选按钮组件设置默认选项时遇到了令人惊讶的困难 这是我的RadioToggle成分 jsx React DOM var RadioToggle React createClass render function va
  • VideoCamera 获取支持的分辨率

    我使用 DirectShow 库 DirectShowLib 2005 dll 和 C 来捕获摄像机图像 当我定义捕获对象的大小时 我有以下参数 const int VIDEOWIDTH 640 Depends on video devic
  • std::enable_if 和 std::enable_if_t 有什么区别?

    C 14 引入std enable if t 它和有什么区别std enable if 使用上有什么优点或者区别吗std enable if t std enable if t 是 std enable if 的内部 type 的类型别名
  • 使用 Boost:Asio 的游戏服务器如何异步工作?

    我正在尝试创建一个游戏服务器 目前我正在使用线程来制作它 每个对象 玩家 怪物 都有自己的带有 while 1 循环的线程 在其中执行特定的功能 服务器基本上是这样工作的 main some initialization while 1 r
  • Mockito - thenReturn 始终返回 null 对象

    我正在尝试实现 Mockito 来测试特定方法 但 thenReturn 似乎总是返回一个 null 对象 而不是我想要的 CUT public class TestClassFacade injected via Spring priva
  • 如何通过 NUnit 有效地对使用 ADO.NET 和 SQL Server 的 DAL 进行单元测试?

    因此 您在 C 中有一个使用存储库模式的 DAL 并且每个存储库都有一个接口 它由 ADO NET MS SQL Server 和存储过程调用支持 这对于在进行单元测试时对正在其他地方使用的存储库进行存根 模拟非常有用 我喜欢它 不过 我很