单元测试数据库方法

时间:2011-10-16 19:35:20

标签: c# unit-testing

我目前正在开发一个使用SQLite数据库的c#项目。对于项目,我需要进行单元测试,但被告知单元测试不应涉及外部文件,例如测试的数据库文件,而是测试应该模拟数据库。

如果我有一个测试数据库中是否存在某个东西的函数,那么如何使用单元测试来测试这种方法。

6 个答案:

答案 0 :(得分:2)

一般来说,如果外部文件避免,一切都在代码中完成,它会让生活更轻松。没有规则说“不应该”,有时只有更有意义才能拥有外部依赖。但只有在你考虑过如何不拥有它之后,才能意识到这些权衡是什么。

其次,布莱恩所说的是一个很好的选择,也是我以前用过的选择。

答案 1 :(得分:2)

在使用数据库的应用程序中,至少有一个组件负责与该数据库通信。该组件的单元测试可能涉及模拟数据库,但使用真实数据库测试组件是完全有效的(并且通常是可取的)。毕竟,组件应该封装和代理与该数据库的通信 - 单元测试应该测试它。有许多策略可以方便地执行此类单元测试 - 请参阅侧栏中的相关SO问题列表以获取示例。

避免在单元测试中访问数据库的一般处方适用于非数据库组件。由于非数据库组件通常大大超过数据库相关组件,因此绝大多数单元测试不应涉及数据库。实际上,如果这些非数据库组件需要数据库进行有效测试,则可能存在设计问题 - 可能是关注点分离不当。

因此,单元测试应该避免数据库的原则通常是正确的,但它不是绝对的规则。它只是一个(强)指导,有助于构建复杂的系统。遵循规则太严格使得很难充分测试封装外部系统的“边界”组件 - 错误发现它很容易隐藏的地方!因此,当单元测试需要数据库时,人们应该真正问自己的问题是:被测试的组件是否直接合法地访问数据库,还是应该与负有该责任的另一个人合作?

同样的推理也适用于在单元测试中使用外部文件和其他资源。

答案 2 :(得分:1)

使用SQLite,您可以使用in-memory database。您可以通过插入数据来暂存数据库,然后针对它运行测试。

答案 3 :(得分:1)

一旦涉及数据库,它总是模糊单元测试和集成测试之间的界限。话虽如此,能够将某些东西放入数据库(安装程序),进行测试并在最后删除它(清理)总是一个很好且非常有用的测试。这使您可以测试应用程序的端到端部分。

我个人喜欢以属性驱动的方式做这件事。通过指定为每个测试运行的Sql脚本作为属性,如此...

[PreSqlExecute("SetupTestUserDetails.sql")]
[PostSqlExecute("CleanupTestUserDetails.sql")]
public void UpdateUserNameTest()
    {

连接字符串像往常一样来自app.config,甚至可以是主项目中app.config的符号链接。

不幸的是,这不是Visual Studio附带的MS测试运行器的标准功能。如果您使用Postsharp作为您的AOP框架,这很容易做到。如果没有,通过使用名为“Context Bound Objects”的.Net功能,您仍然可以获得标准MS Test Runner的相同功能。这样,只要您的对象继承自ContextBoundObject,就可以将自定义代码注入对象创建链中以执行类似AOP的操作。

我在博客文章中提供了更多详细信息以及一个小而完整的代码示例。

http://www.chaitanyaonline.net/2011/09/25/improving-integration-tests-in-net-by-using-attributes-to-execute-sql-scripts/

答案 4 :(得分:0)

我认为依靠数据库信息进行单元测试真是个坏主意。 我认为使用sqlite进行单元测试也是一个坏主意。

你需要测试对象协议,所以如果你在测试中需要一些东西,你应该在测试中的某个地方创建它们(通常是在setUp)。

由于很难删除持久性,因此流行的方法是使用SQLite,但始终在单元测试中创建所需的内容。

检查此链接Unit Tests And Databases我认为这会更有帮助

答案 5 :(得分:0)

最好使用模拟框架来模仿数据库。对于C#,有Entity Framework。即使使用sqlite也是对代码的外部依赖。