如何在.Net中编写数据访问层测试?
有没有为数据访问层编写单元测试的框架?这里面有几个问题。
1. 如何填充数据库?
2. 我们如何确保一个测试不会修改数据库中的值,从而导致另一测试失败?
有没有一个好的框架可以解决上述问题?
更新:我遇到了 nDBUnit,它可以通过测试数据访问层来解决基础设施问题。
Is there a framework to write unit test for Data Access layer? There are several issues in this.
1. How to populate your database?
2. How do we make sure that one test is not modifying values in db that can fail another test?
Is there a good framework available which can take care of above issues?
Update: I came across nDBUnit which can take care of infrastructure issues with testing data access layer.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我想我会插话,因为到目前为止我真的不喜欢一些答案。
在这种情况下,无论你称其为“单元测试”、“集成测试”还是“supercalifragilisticexpialidocious 测试”,都无关紧要。对于数据访问组件只有一种有效的测试,那就是在实际数据上进行测试。显然不是生产数据,而是其合理的传真。
您需要做的第一件事是 将数据库本身置于源代码控制之下。遗憾的是,目前还没有这样的框架。微软在 VSTS 的某些版本中采取了部分措施,但最终结果仍然有些欠缺。至少在当今世界,你必须自己做很多这样的工作。但请认真执行 - 当重大更新失败并且您需要回滚数据库时,您不会后悔。
置于源代码控制之下的内容应该是生成最新模式所需的一切,通常是基线脚本,加上“配置数据”脚本(即枚举表的内容)以及升级脚本以反映最近的模式更改。这为您提供了在临时数据库上执行“实时”测试所需的几乎一切;您的测试只需要从源代码管理下载这些脚本并在测试服务器和/或不同的数据库实例上运行它们,通常使用 SQL 管理对象来运行所述脚本(SMO 可以处理
GO
语句等;常规的SqlConnection
不能)。各种工具可以帮助您在测试数据库中生成测试内容。最流行的可能是 Red Gate 的 SQL 数据生成器。这些工具还可以生成脚本来创建数据,这就是您将在测试中使用的数据。或者,如果您愿意,您可以从生产数据库中清理数据,并使用 SQL Server Management Studio 编写您选择保留用于测试的任何数据的脚本。无论哪种方式,将测试数据脚本保留在源代码管理中,与架构脚本相同,并且当您需要测试 DAL 时,请在启动数据库实例后下载这些脚本并使用它们来填充数据。
我希望有一个框架可以为您完成所有这些工作,但是通过正确的工具、库和良好的开发实践集合,您可以将其变成一个不那么痛苦的过程。
I guess I'll chime in, since I really dislike some of the answers so far.
Whether you call it a "unit test" or "integration test" or a "supercalifragilisticexpialidocious test" does not matter one bit in this instance; there's only one valid test for data access components and that it is to test it on actual data. Not production data obviously, but a reasonable facsimile thereof.
The very first thing you need to do is get the database itself under source control. Sadly, there is no framework for this; Microsoft goes part of the way in some versions of VSTS but the end result is still somewhat lacking. At least in today's world, you're going to have to do a lot of this work yourself. But do it, seriously - you won't regret it when a major update gets botched and you need to roll back the DB.
What you put under source control should be everything necessary to generate the newest schema, usually a baseline script, plus "configuration data" scripts (i.e. the contents of enumeration tables), and upgrade scripts to reflect recent schema changes. This gives you almost everything you need to perform "live" testing on a temporary database; your test only needs to download those scripts from source control and run them on a test server and/or a different database instance, usually using SQL Management Objects to run said scripts (SMO can handle
GO
statements and the like; a regularSqlConnection
cannot).Various tools can help you with the generation of test content in the test database. Probably the most popular is Red Gate's SQL Data Generator. These tools can also generate scripts to create the data, which is what you'll be using in your tests. Or, if you so choose, you can scrub the data from your production database and use SQL Server Management Studio to script whatever data you choose to keep for testing. Either way, keep your test data scripts in source control, same as the schema scripts, and when you need to test your DAL, download these scripts after firing up a DB instance and use them to populate the data.
I wish there were a single framework that would do all of this for you, but with the right collection of tools, libraries, and good development practices, you can make this into a much less painful process.
真正的单元测试不会访问数据库。也就是说,mbUnit 有一个回滚属性,可用于访问数据库的测试。
True unit tests wouldn't access the db. That said, mbUnit has a rollback attribute that can be used for tests that do access the db.
当您测试将访问数据库的存储库时,您必须始终确保在单元测试完成后清除数据库。您可以通过在事务下运行测试来执行此操作,也可以使用 MbUnit Rollback 属性自动回滚更改。
When you are testing your repositories which will access the database you must always make sure that database is cleared after the unit test is complete. You can perform this by running the test under the transaction OR you can use MbUnit Rollback attribute to rollback the changes automatically.
不。单元测试不访问数据库。这就是集成或功能测试的用途。
我将进行一组测试来验证管理数据库通信的代码是否正在做正确的事情,然后尽可能不频繁地触及它。
不在“单元测试”中这样做的原因是,这样做会冒淡化“单元测试”一词含义的风险,将它们变成测试的抓包,这通常会使它们变慢并阻止开发人员不应频繁地运行它们。
Don't. Unit tests don't access the db. That's what integration or functional tests are for.
I'd have a set of tests that validate that the code that manages the db communication is doing the right thing, and then touch it as infrequently as possible.
The reason to not do it in 'unit tests' is that by doing so, you run the risk of diluting the meaning of the phrase 'unit test', turning them into a grab bag of tests, which will typically make them slower and prevent developers from running them as frequently as they should.