模拟与测试数据库?

发布于 2024-07-08 14:41:25 字数 366 浏览 7 评论 0原文

早些时候我问过这个问题如何正确地对我的 DAL 进行单元测试?,我没有回答的一件事是,如果真正测试我的 DAL 就是拥有一个测试数据库,那么模拟与测试数据库的作用是什么?

除此之外,另一个人建议“在单元测试结束时使用事务和回滚,因此数据库是干净的”,即测试数据库。 你们觉得这种测试+测试DB+事务回滚(所以db不是真正写的)测试DAL的方法怎么样?

完整地说,我的 DAL 是使用实体框架构建的,数据库中没有存储过程。 由于 EF 太新了,我确实需要测试 DAL 以确保它们正常工作。

Earlier I asked this question How to correctly unit test my DAL?, one thing left unanswered for me is if to really test my DAL is to have a Test DB, then what is the role of mocking vs. a testing DB?

To add on this, another person suggested to "use transactions and rollback at the end of the unit test, so the db is clean", test db that is. What do you guys think of this testing + test DB + transaction rollback (so db is not really written) approach to test DAL?

To be complete, my DAL is built with Entity Framework, there is no stored proc in DB. Since EF is so new, I really need to test DAL to make sure they work correctly.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

给我一枪 2024-07-15 14:41:25

我认为您可能需要进行一些集成测试来检查数据库结构强制执行的逻辑,例如约束、触发器、自动增量列等。但是,对于单元测试,您应该模拟 DAL 所使用的任何框架组件根据您的需要(在单元测试中)依赖来仅测试您已编码的那些组件。 您实际上并不需要测试 SqlCommand 或 SqlConnection 上的方法(例如)。 您应该假设您使用的框架组件可以工作,并为它们创建存根或模拟,将已知数据(好的、坏的、异常)返回到您的方法,以确保您的方法正常工作。 如果不进行模拟,您将负责在数据库中生成数据并确保其正确。 您还保留了对网络、数据库本身等的开放依赖关系,这可能会使您的测试变得脆弱。

此外,单元测试并不能消除对其他类型测试的需要。 集成测试和验收测试仍然有效并且需要完成。 它们可能不需要以与单元测试相同的频率完成,也可能不需要像通过单元测试提高代码质量一样广泛,但单元测试并不是灵丹妙药。

I think you'll probably want to do some integration testing to check logic that is enforced by your database structure, for example constraints, triggers, autoincrement columns, etc. You should, however, for unit testing mock out whatever framework components that your DAL relies upon as you want (in your unit tests) to test only those components that you have coded. You don't really need to test methods on SqlCommand or SqlConnection (for example). You should assume that the framework components that you use work and create stubs or mocks for them that return known data (good, bad, exceptions) to your methods to make sure that your methods work properly. Without mocking you are responsible for generating the data in the database and making sure that it is correct. You also leave open dependencies on the network, the database itself, etc. that may make your tests brittle.

Also, unit testing does not remove the need for other types of testing. Integration tests and acceptance tests are still valid and need to be done. They probably don't need to be done with the same frequency as unit tests and may not need to be as extensive as your code quality improves with unit testing, but unit testing is not a magic bullet.

梦归所梦 2024-07-15 14:41:25

在测试数据访问代码时,我没有发现模拟非常有用。 单元测试的目的是验证与数据库相关的代码是否有效,模拟数据库会阻碍测试。

在测试业务代码时,模拟确实变得有用。 您可以模拟数据库调用以返回测试数据并验证业务逻辑在这些情况下的行为。

关于事务的使用 - 这当然是可能的,只要您的体系结构有空间在测试开始时启动事务,然后在该事务内执行单元测试的所有与数据库相关的调用。 但从未尝试过。

I didn't find mocking very useful when testing data access code. The purpose of unit testing is to verify the database-related code works and mocking the database would hinder the test.

Mocking does indeed become useful when testing the business code. You can mock your database calls to return test data and verify the behavior of business logic in those circumstances.

Regarding the use of transactions - it's certainly possible, as long as your architecture has room for starting a transaction at the beginning of the test, and then doing all database-related calls of your unit test inside that transaction. Never tried it, though.

歌枕肩 2024-07-15 14:41:25

将单元测试放入可回滚的事务中听起来很老套。
相反,我有代码在测试运行之前(即在我的测试类的构造函数中)清除数据库中的任何 CRUD(即不是静态/引用数据的任何内容)。 当测试失败时,将数据保留在数据库中有助于检查失败的原因。

Putting unit tests into transactions that roll back sounds hacky.
Instead of that I have code that cleans the database of any crud (i.e. anything that isn't static/reference data) before the tests run (i.e. in the constructor of my test class). When your tests fail it helps to have the data still in the database to inspect what the cause of the failure is.

扬花落满肩 2024-07-15 14:41:25

我们使用了事务性单元测试,并多次防止了 Hibernate 映射问题。 否则 - 什么是单元测试? 像 List这样的小事 getAllItems()? :)

we've used transactional unit tests and that prevented Hibernate mapping problems several times. Otherwise - what's to unit test? Something trivial as List<Item> getAllItems()? :)

农村范ル 2024-07-15 14:41:25

不过,您不仅仅是测试您的应用程序。 您还将测试您的配置以及存储过程和视图。 这些记录在您的单元测试中。

Your not just testing your app, though. You are also testing your configuration and your Stored Procedures and Views. These are documented in your unit tests.

粉红×色少女 2024-07-15 14:41:25

通过使用测试数据库,您就有可能在数据库本身或 DAL 与数据库之间的通信路径(网络等)上引起问题。 模拟消除了这些可能性。

By using a test database, you open up the possibility that problems could be caused at the database itself or along the communication path (network, etc) between the DAL and database. Mocking eliminates those possibilities.

栩栩如生 2024-07-15 14:41:25

您不仅必须考虑数据库的状态,还必须考虑可用性。 如果您的数据库离线,为什么所有 DAL 测试都会失败?

您需要测试的是您的 DAL 发出正确的命令来创建/检索/更新/删除。 您不需要为此执行 SQL,您只需使用对象持久性框架并检查您是否为其提供了正确的指令。

It's not only the state of the DB you must consider, it's also availability. If your DB is offline why should all of your DAL tests fail?

What you need to test is that your DAL issues the correct commands in order to create / retrieve / update / delete. You don't need to execute SQL for this, you can just use an object persistence framework and check that you give it the correct instructions.

往日情怀 2024-07-15 14:41:25

问题很可能出在原来的问题上。 一些更流行的 MVC 示例通过返回 DbSet 来使用快捷方式,例如:

public class MusicStoreEntities : DbContext
    {
        public DbSet<Album> Albums { get; set; }
        public DbSet<Genre> Genres { get; set; }
        public DbSet<Artist> Artists { get; set; }
        public DbSet<Cart> Carts { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<OrderDetail> OrderDetails { get; set; }
    }

对我来说,这与持久性的实现紧密结合,我认为这是一件坏事。 最好返回很容易被嘲笑的 List

The problem could very well be in the original question. Some of the more popular examples of MVC use a shortcut by returning a DbSet such as:

public class MusicStoreEntities : DbContext
    {
        public DbSet<Album> Albums { get; set; }
        public DbSet<Genre> Genres { get; set; }
        public DbSet<Artist> Artists { get; set; }
        public DbSet<Cart> Carts { get; set; }
        public DbSet<Order> Orders { get; set; }
        public DbSet<OrderDetail> OrderDetails { get; set; }
    }

To me this tightly couples the implementation of persistence which I believe is a bad thing. It woud be better to return List<t> which could easily be mocked.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文