我喜欢Rails和Django测试方法的一件事是它们支持在每次测试运行之前使用夹具来设置数据库。
过去,我将严格的单元测试与模拟存储库结合使用来测试我的代码,但我希望拥有与上述测试方法一样易于使用的东西,以便进行集成测试。
我听说过一些关于代码优先和 EF 5 的此类支持的讨论,但我不知道它是否达到了 Rails 和 Django 提供的水平。
当然,那里有可比的东西。任何信息,将不胜感激!
在 EF5 中引入了新概念,称为Migrations。您可能曾经在 Rails 或 Django 应用程序中使用过类似的东西。
迁移是一个类,具有升级/降级数据库版本的多种功能。
public partial class VoteTime : DbMigration
{
public override void Up()
{
AddColumn("Votes", "Time", c => c.DateTime(nullable:false, defaultValue:DateTime.UtcNow));
}
public override void Down()
{
DropColumn("Votes", "Time");
}
}
您还必须设置 DbContext 和 DbMigrationsConfiguration 配置类以允许代码优先方法工作。
出于测试目的,您需要引入,TestDatabaseInitilizer
public class TestDatabaseInitilizer : DropCreateDatabaseAlways<DbContext>
{
}
它将负责为单元测试初始化测试数据库。
最后,您应该设计测试代码来设置上下文。
public class SomeRepositoryTests
{
private DbContext _context;
[SetUp]
public void Setup()
{
Database.SetInitializer(new TestDatabaseInitilizer());
_context = new DbContext("TestContext");
_repository = new SomeRepository(_context);
}
[Test]
public void should_return_some_entities()
{
Assert.That(_repository.Get(), Is.Not.Null);
}
}
如果需要,可以将设置代码移至基类。
我使用实体框架开发了一个应用程序,该应用程序具有 600 多个自动化集成测试。这是我使用的过程:
Entity Framework 代码首先迁移只是为了设置数据库结构(表、索引等)。我不使用迁移来播种数据。
将数据库设置为特定的、众所周知的状态的 SQL 脚本。例如,一个插入 ASP.NET 会员用户的脚本;另一个为最相关的表格设置样本数据;和其他更具体的场景。脚本通常从适当的表中删除记录,然后以适当的顺序再次插入它们以避免关系冲突。这些脚本作为嵌入式资源包含在 Visual Studio 项目中。
一个帮助类,它可以通过名称从资源中获取脚本并针对数据库执行它,包括带有“GO”的批处理命令。ConnectionContext.ExecuteNonQuery 可以用于此。
在整个测试套件开始时,我执行设置用户、权限和其他非常通用的环境配置的脚本。
在每种测试方法之前,我会根据需要执行一个或多个脚本,以在运行测试所需的上下文中设置数据库。例如,在一系列读取、插入、更新和删除数据的 CRUD 测试之前,我运行了一个脚本,该脚本使用测试数据为适当的表提供种子。
我假设数据库设置在特定的上下文中编写测试用例。例如,更新操作的测试将尝试检索具有已知键的记录,更新它并再次读取以检查它是否在数据库中更新。
尽管 SQL 脚本不像 Rails 固定装置那样容易编写和阅读,但它们非常快并且可以进行任何需要的操作(例如,删除、插入、更新、执行存储过程)。
这种技术在一个涉及 50 个数据库表和非常复杂的业务规则和流程的项目中得到了很好的证明。它使测试保持简单和一致。