用于单元测试的内存 DBMS
Posted
技术标签:
【中文标题】用于单元测试的内存 DBMS【英文标题】:In-memory DBMS's for unit testing 【发布时间】:2010-10-03 17:43:35 【问题描述】:我正在寻找令人满意的选项来对我的 .NET DAL 类进行单元测试;因为它们是 DAL 类,所以它们直接使用 ADO.NET 访问数据库。目前我使用 MSSQL 数据库的实例进行测试,但想知道有哪些更快的选项——因为单元测试需要尽快运行,所以内存中的解决方案是理想的。
我还应该提到,我将自己绑定到 TSQL,因为我只会使用 Microsoft 平台。
【问题讨论】:
【参考方案1】:鉴于您声明:
我还应该提到我已经绑定了 我自己到 TSQL,因为我只是曾经 将使用微软 平台。
然后使用 SqlServer 精简版可能会很好地满足您的需求。 它不会完全在内存中运行,但可以在只读模式下运行(不会对主数据库文件进行编辑,因此可以同时被多个测试使用)
有一些陷阱,不支持存储过程,需要翻译一些数据类型,并且某些数据类型有严格的限制(特别是 varchar,它只能达到 4000 个字符) Linq to Sql 也没有得到适当的支持。
尽管如此,我使用 SqlServer 精简版几乎完全替代了适当的 Sql Server 数据库,效果很好。
【讨论】:
我认为Linq to Sql 是从那以后实现的?【参考方案2】:我发现SQLite 是最佳选择。虽然,我使用的是 nHibernate,但它是零配置,所以只需要一秒钟的时间来设置。不过,您必须注意,这些类型的引擎通常缺少您可能需要的一些东西(例如,如果您使用 ADO 提供程序,当表名中有空格时,SQLite 会爆炸)
当然,@TopBanana 关于不使用“实际”数据库的一些问题是正确的。但是,内存中的 RDBMS 非常适合您想要快速运行的那些类型的测试(例如,增量或 CI 构建的签入测试)。
另一个巨大的优势是您不必担心设置或拆卸。由于开发人员 A 破坏了您的开发数据库,因此您的签入失败是非常低效的 ;-)
【讨论】:
这里是 SQLite ado.net 提供者 sqlite.phxsoftware.com 的链接。要使用内存数据库,请使用带有 :memory: 的连接字符串。 IMO,您应该只在 CI 构建期间使用数据库测试您的 DAL。上层应该得到一个没有 db 的 DAL 模拟。 只有一个问题 - SQLite 不支持 TSQL! 哎呀,对不起。也许他应该尝试使用 SQL Server Compact - snurl.com/au31q 它可以在一定程度上应对 TSQL - 在这里阅读比较:snurl.com/au3d0。它不是内存数据库,而是轻量级数据库,不需要服务,只需要 DLL。但是它仍然写入磁盘。 我写的几乎和 ShuggyCoUk 一样。但我想没关系,因为我提供了链接。【参考方案3】:听说windows有挂载ramdisk的软件(不记得url了,不好意思)。
在此基础上创建测试数据库可能会很有趣。
【讨论】:
我实际上已经用 ImgDisk 尝试过这条路线。我为每个测试创建/销毁数据库。在我的场景中,这并没有比将数据库放在 SSD 上快得多(慢)。所以现在我正在研究在内存中使用 SQLite 或使用 DI 和模拟的通常路线。【参考方案4】:SQL Server真的是您单元测试的瓶颈吗?
我的意思是:
-
您是否对单元测试进行了概要分析(使用 SQL Profiler 之类的工具)。他们都慢吗?有几个慢?为什么?
您的单元测试做得太多了吗?设置和拆卸代码是否过于繁重?
如果 SQL 是您的瓶颈,您是否考虑过 mocking framework,因此您模拟了所有 SQL 调用。
【讨论】:
使用模拟框架会发生什么?假设我有一个 PersonService。该 PersonService 有一个方法 GetAllPersons 来返回所有人。在该方法中,我统一提供了 IPersonDataAcces 的实现,它具有 GetAllPersons() 方法。在生产中,实现转到 sql server 并获取所有人员。如果我使用模拟框架会发生什么?我想我也有统一给我一个 IPersonDataAcces 的实现,但是然后是一个“嘲笑”的?那么如果我调用 GetAllPersons() 方法会发生什么?在测试 PersonService 时我要断言什么?【参考方案5】:我在使用 Oracle 时遇到了类似的挑战,我们做了以下事情:
确保真正的单元测试不会触及数据库,而是使用模拟服务来代替
实际需要 Oracle 的标记数据库测试与可以针对 HSQLDB 或 H2 或任何其他内存数据库运行的测试。所以我们可以分别运行它们。
在实际使用 Oracle 功能的测试中,我们使用了在 RAM 磁盘上运行的普通 Oracle 实例。
这大大加快了测试速度。
【讨论】:
只解决单元测试的性能问题。但理想情况下,我需要一种更简单的方法来在单元测试中对测试数据进行编码,就像我为依赖方法注册任何存根实现一样。在真实数据库中准备数据有点复杂。【参考方案6】:我建议您对单元测试使用与生产相同的数据库。在调试实时问题时,您真的不需要一些奇怪的区别。
如果您查看 NHibernate 的真正大型单元测试套件,您会发现它使用 SQL Server(基于磁盘),并且测试运行速度惊人。考虑到比一般的单元测试集要多得多的表创建/删除,这更令人印象深刻,这不是 SQL Server 优化的目标。
【讨论】:
以上是关于用于单元测试的内存 DBMS的主要内容,如果未能解决你的问题,请参考以下文章
如何在用于运行 Java 单元测试的内存数据库中模拟 Oracle (+) 外连接表示法?
Visual Leak Detector 不适用于 VS2012 中的单元测试
出于单元测试的目的,哪个内存 Java 数据库最接近 MySQL 和 SqlServer?