之前我问过这个问题How to correctly unit test my DAL?,有一件事我没有回答,如果要真正测试我的DAL是否有测试数据库,那么模拟与测试数据库的作用是什么?
为了补充一点,另一个人建议“在单元测试结束时使用事务和回滚,因此db是干净的”,测试db就是。你们怎么看待这个测试+测试DB +事务回滚(所以数据库没有真正编写)的方法来测试DAL?
要完成,我的DAL是使用Entity Framework构建的,DB中没有存储过程。由于EF是如此新颖,我真的需要测试DAL以确保它们正常工作。
答案 0 :(得分:14)
我认为您可能希望进行一些集成测试来检查由数据库结构强制执行的逻辑,例如约束,触发器,自动增量列等。但是,您应该对单元测试模拟出任何框架组件您的DAL依赖于您(在单元测试中)仅依赖于您已编码的那些组件。您实际上不需要在SqlCommand或SqlConnection上测试方法(例如)。您应该假设您使用的框架组件工作并为它们创建存根或模拟,以便为您的方法返回已知数据(好的,坏的,例外),以确保您的方法正常工作。没有嘲笑,你负责在数据库中生成数据并确保它是正确的。您还会在网络,数据库本身等上留下开放的依赖关系,这可能会使您的测试变得脆弱。
此外,单元测试不会消除对其他类型测试的需求。集成测试和验收测试仍然有效,需要完成。它们可能不需要以与单元测试相同的频率完成,并且可能不需要像单元测试那样提高代码质量,但单元测试不是灵丹妙药。
答案 1 :(得分:8)
在测试数据访问代码时,我没有发现mocking非常有用。单元测试的目的是验证与数据库相关的代码是否正常工作,并且模拟数据库会妨碍测试。
在测试业务代码时,Mocking确实很有用。您可以模拟数据库调用以返回测试数据,并在这些情况下验证业务逻辑的行为。
关于事务的使用 - 只要您的体系结构在测试开始时有空间启动事务,然后在该事务中执行单元测试的所有数据库相关调用,这当然是可能的。但是从未尝试过。
答案 2 :(得分:3)
将单元测试放入回滚的交易中听起来很糟糕。 而不是我在测试运行之前(即在我的测试类的构造函数中)有代码清除任何crud的数据库(即任何非静态/引用数据)。当测试失败时,有助于使数据仍在数据库中以检查失败的原因是什么。
答案 3 :(得分:1)
我们使用了事务单元测试,并且多次阻止了Hibernate映射问题。否则 - 什么是单元测试?像List<Item> getAllItems()
那样微不足道的东西? :)
答案 4 :(得分:0)
通过使用测试数据库,您可能会在数据库本身或DAL与数据库之间的通信路径(网络等)上产生问题。模拟消除了这些可能性。
答案 5 :(得分:0)
这不仅是你必须考虑的数据库的状态,它也是可用性。如果您的数据库处于脱机状态,为什么所有DAL测试都会失败?
您需要测试的是您的DAL发出正确的命令以创建/检索/更新/删除。您不需要为此执行SQL,您只需使用对象持久性框架并检查是否给出了正确的指令。
答案 6 :(得分:0)
不仅仅是测试你的应用程序。您还在测试您的配置以及存储过程和视图。这些都记录在您的单元测试中。
答案 7 :(得分:-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>
会更容易被嘲笑。