31

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

为了补充这一点,另一个人建议“在单元测试结束时使用事务和回滚,所以数据库是干净的”,即测试数据库。你们如何看待这种测试 DAL 的测试 + 测试 DB + 事务回滚(所以 db 不是真正编写的)方法?

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

4

8 回答 8

17

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

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

于 2008-11-21T21:50:51.937 回答
11

在测试数据访问代码时,我发现模拟并不是很有用。单元测试的目的是验证与数据库相关的代码是否正常工作,模拟数据库会阻碍测试。

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

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

于 2008-11-21T21:54:17.157 回答
3

将单元测试放入回滚的事务中听起来很老套。取而代之的是,我有代码在测试运行之前(即在我的测试类的构造函数中)清除任何 crud 的数据库(即任何非静态/参考数据)。当您的测试失败时,将数据保留在数据库中以检查失败的原因是有帮助的。

于 2009-02-06T22:06:18.620 回答
1

我们已经使用了事务性单元测试,并且多次阻止了 Hibernate 映射问题。否则 - 什么是单元测试?微不足道的东西List<Item> getAllItems()?:)

于 2008-11-22T00:14:22.583 回答
0

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

于 2008-11-21T21:44:26.273 回答
0

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

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

于 2009-02-06T22:09:51.763 回答
0

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

于 2012-09-20T16:48:38.013 回答
-1

问题很可能出在原始问题中。一些更流行的 MVC 示例通过返回 a 来使用快捷方式,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<t>容易被嘲笑的东西。

于 2012-09-06T15:03:49.477 回答