简体   繁体   English

单元测试数据库方法

[英]Unit Testing Database Methods

I am currently working on ac# project which makes use of an SQLite Database. 我目前正在研究使用SQLite数据库的ac#项目。 For the project I am required to do unit testing but was told that unit testing shouldn't involve external files, like database files for the testing and instead the test should emulate the database. 对于该项目,我需要进行单元测试,但被告知单元测试不应包含外部文件(例如用于测试的数据库文件),而是应该模拟数据库。

If I have a function that tests if a something exists in a database how could this sort of method be tested with a unit testing. 如果我有一个测试数据库中是否存在某些东西的函数,那么如何用单元测试来测试这种方法。

in general it makes life easier if external files are avoided and everything is done in code. 通常,如果避免使用外部文件并且所有操作均通过代码完成,则可使工作变得更轻松。 There are no rules which says "shouldn't", and sometimes it just makes more sense to have the external dependency. 没有规则说“不应该”,有时具有外部依赖才更有意义。 But only after you have considered how not to have it, and realized what the tradeoffs are. 但是只有在您考虑了如何不拥有它,并且意识到了权衡之后,才有可能。

Secondly, what Bryan said is a good option and the one I've used before. 其次,Bryan所说的是一个不错的选择,而我以前使用过。

In an application that uses a database, there will be at least one component whose responsibility is to communicate with that database. 在使用数据库的应用程序中,将至少有一个组件负责与该数据库进行通信。 The unit test for that component could involve a mocked database, but it is perfectly valid (and often desirable) to test the component using a real database. 该组件的单元测试可能包含模拟数据库,但是使用真实数据库测试该组件是完全有效的(并且通常是合乎需要的)。 After all, the component is supposed to encapsulate and broker communication with that database -- the unit test should test that. 毕竟,该组件应该封装并代理与该数据库的通信-单元测试应该对此进行测试。 There are numerous strategies to perform such unit tests conveniently -- see the list of related SO questions in the sidebar for examples. 有许多策略可以方便地执行此类单元测试-有关示例,请参见侧栏中的相关SO问题列表。

The general prescription to avoid accessing databases in unit tests applies to non-database components. 避免在单元测试中访问数据库的一般规定适用于非数据库组件。 Since non-database components typically outnumber database-related components by a wide margin, the vast majority of unit tests should not involve a database. 由于非数据库组件通常会大大超过与数据库相关的组件,因此绝大多数单元测试不应涉及数据库。 Indeed, if such non-database components required a database to be tested effectively, there is likely a design problem present -- probably improper separation of concerns. 的确,如果此类非数据库组件要求对数据库进行有效测试,则可能存在设计问题-可能是关注点分离不当。

Thus, the principle that unit tests should avoid databases is generally true, but it is not an absolute rule. 因此,单元测试应避免使用数据库的原则通常是正确的,但这不是绝对的规则。 It is just a (strong) guideline that aids in structuring complex systems. 这只是(强)指南,有助于构造复杂的系统。 Following the rule too rigidly makes it very difficult to adequately test "boundary" components that encapsulate external systems -- places in which bugs find it very easy to hide! 过于严格地遵循该规则,很难充分测试封装外部系统的“边界”组件,在这些地方,错误很容易隐藏! So, the question that one should really be asking oneself when a unit test demands a database is this: is the component under test legitimately accessing the database directly or should it instead collaborate with another that has that responsibility? 因此,当单元测试需要一个数据库时,一个人应该真正问自己的问题是:被测试的组件是直接合法地访问数据库,还是应该与具有该职责的另一个人协作?

This same reasoning applies to the use of external files and other resources in unit tests as well. 同样的道理也适用于在单元测试中使用外部文件和其他资源。

With SQLite, you could use an in-memory database . 使用SQLite,您可以使用内存数据库 You can stage your database by inserting data and then run your tests against it. 您可以通过插入数据来暂存数据库,然后对其进行测试。

Once databases get involved it always blurs the line between unit testing and integration testing. 一旦数据库参与进来,它总是会模糊单元测试和集成测试之间的界线。 Having said that, it is always a nice and very useful test to be able to put something in a database (Setup), Do your test and remove it at the end (Cleanup). 话虽如此,能够将某些东西放入数据库中(设置)始终是一个很好且非常有用的测试,进行测试并最后将其删除(清理)。 This lets you test end to end one part of your application. 这使您可以测试应用程序的端到端部分。

Personally I like to do this in an attribute driven fashion. 我个人喜欢以属性驱动的方式进行此操作。 By Specifying the Sql scripts to run for each test as an attribute like so .. 通过指定要为每个测试运行的Sql脚本作为属性,如..

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

The connectionstrings come from the app.config as usual and can even be a symbolic link to the app.config in your main project. 连接字符串通常来自app.config,甚至可以是到主项目中app.config的符号链接。

Unfortunately this isn't a standard feature with the MS test runner that ships with visual studio. 不幸的是,这不是Visual Studio附带的MS测试运行程序的标准功能。 If you are using Postsharp as your AOP framework, this is easy to do. 如果您将Postsharp用作AOP框架,则很容易做到。 If not, you can still get the same functionality for standard MS Test Runner, by using a feature of .Net called "Context Bound Objects". 如果没有,您仍然可以通过使用.Net的“上下文绑定对象”功能来为标准MS Test Runner获得相同的功能。 This lets you inject custom code into an object creation chain to do AOP like stuff as long as your objects inherit from ContextBoundObject. 这样,只要您的对象从ContextBoundObject继承,就可以将自定义代码注入到对象创建链中以进行AOP之类的工作。

I did a blog post with more details and a small, complete code sample here. 我在博客文章中提供了更多详细信息,并在此处提供了一个完整的小型代码示例。

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

It's best to use a mocking framework, to mimic a database. 最好使用模拟框架来模拟数据库。 For C# there is the Entity Framework . 对于C#,有实体框架 Even the use of sqlite is an outside dependency to your code. 甚至使用sqlite都是代码的外部依赖。

I think is really bad idea to have unit tests that depends on database information. 我认为进行依赖于数据库信息的单元测试确实是一个坏主意。 Also I think is a bad idea to use sqlite for unit tests. 同样,我认为使用sqlite进行单元测试不是一个好主意。

You need to test objects protocol, so if you need something in your tests you should create them somewhere in the tests (usually at setUp). 您需要测试对象协议,因此,如果您在测试中需要某些东西,则应在测试中的某个位置(通常是在setUp处)创建它们。

Since is difficult to remove persistence, the popular way to do it is using SQLite, but always create what you need in unit tests. 由于很难消除持久性,因此流行的方法是使用SQLite,但始终在单元测试中创建所需的内容。

check this link Unit Tests And Databases this will be more helpful I think 检查此链接单元测试和数据库,我认为这将更加有用

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM