模拟与测试数据库?
Posted
技术标签:
【中文标题】模拟与测试数据库?【英文标题】:Mocking vs. Test DB? 【发布时间】:2010-09-23 13:02:54 【问题描述】:之前我问过这个问题How to correctly unit test my DAL?,对我来说没有答案的一件事是,如果要真正测试我的 DAL 是要有一个测试数据库,那么模拟与测试数据库的作用是什么?
为了补充这一点,另一个人建议“在单元测试结束时使用事务和回滚,所以数据库是干净的”,即测试数据库。你们如何看待这种测试 DAL 的测试 + 测试 DB + 事务回滚(所以 db 并不是真正编写的)方法来测试 DAL?
完整地说,我的 DAL 是使用实体框架构建的,DB 中没有存储过程。由于 EF 太新,我真的需要测试 DAL 以确保它们正常工作。
【问题讨论】:
【参考方案1】:问题很可能出在原始问题中。一些更流行的 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<t>
,这很容易被嘲笑。
【讨论】:
【参考方案2】:不过,您不只是在测试您的应用。您还在测试您的配置以及您的存储过程和视图。这些都记录在您的单元测试中。
【讨论】:
【参考方案3】:您必须考虑的不仅仅是数据库的状态,还有可用性。如果您的数据库处于脱机状态,为什么您的所有 DAL 测试都会失败?
您需要测试的是您的 DAL 发出正确的命令以创建/检索/更新/删除。你不需要为此执行 SQL,你可以使用一个对象持久化框架并检查你是否给出了正确的指令。
【讨论】:
【参考方案4】:将单元测试放入回滚的事务中听起来很老套。 取而代之的是,我有代码在测试运行之前(即在我的测试类的构造函数中)清除任何 crud 的数据库(即任何不是静态/参考数据的东西)。当您的测试失败时,将数据仍在数据库中以检查失败的原因是有帮助的。
【讨论】:
【参考方案5】:我们已经使用了事务性单元测试,并且多次避免了 Hibernate 映射问题。否则 - 什么是单元测试?像List<Item> getAllItems()
这样微不足道的东西? :)
【讨论】:
【参考方案6】:在测试数据访问代码时,我发现模拟并不是很有用。单元测试的目的是验证与数据库相关的代码是否有效,模拟数据库会阻碍测试。
在测试业务代码时,模拟确实变得有用。您可以模拟您的数据库调用以返回测试数据并验证业务逻辑在这些情况下的行为。
关于事务的使用 - 这当然是可能的,只要您的架构有空间在测试开始时启动事务,然后在该事务中执行单元测试的所有与数据库相关的调用。不过没试过。
【讨论】:
【参考方案7】:我认为您可能需要进行一些集成测试来检查由数据库结构强制执行的逻辑,例如约束、触发器、自动增量列等。但是,对于单元测试,您应该模拟任何框架组件你的 DAL 依赖于你想要的(在你的单元测试中)只测试你编码的那些组件。您实际上不需要在 SqlCommand 或 SqlConnection 上测试方法(例如)。您应该假设您使用的框架组件工作并为它们创建存根或模拟,它们将已知数据(好的、坏的、异常)返回给您的方法,以确保您的方法正常工作。在没有模拟的情况下,您有责任在数据库中生成数据并确保它是正确的。您还会留下对网络、数据库本身等的开放依赖,这可能会使您的测试变得脆弱。
此外,单元测试并不能消除对其他类型测试的需求。集成测试和验收测试仍然有效,需要进行。它们可能不需要以与单元测试相同的频率进行,并且可能不需要像单元测试提高代码质量那样广泛,但单元测试并不是灵丹妙药。
【讨论】:
+1 集成测试仍然占有一席之地。 @ray247 请记住,模拟只是为了测试较低层,例如业务层,因为在这些测试中,您只是想知道您的业务层是否工作......而不是数据库,所以您的模拟将“像一个返回某些东西的数据库一样”。 【参考方案8】:通过使用测试数据库,您可能会在数据库本身或 DAL 和数据库之间的通信路径(网络等)上引起问题。模拟消除了这些可能性。
【讨论】:
有人推荐用test db做事务和回滚,你觉得这种测试DAL的方法怎么样? 交易和回滚,根据我的经验,一直很慢。 你可以通过 mocking 来模拟交易失败引起的异常。以上是关于模拟与测试数据库?的主要内容,如果未能解决你的问题,请参考以下文章
多次使用相同的模拟对象/数组时,如何在没有引用问题的情况下导入模拟数据以进行测试