使用fixture测试实体框架

时间:2012-07-03 23:06:09

标签: c# asp.net-mvc-3 entity-framework unit-testing tdd

我喜欢Rails'Django's测试方法的一个原因是他们支持在每次测试运行之前使用fixture来设置数据库。

过去,我使用严格的单元测试和模拟的存储库来测试我的代码,但是我希望有一些像上述测试方法一样易于使用的东西,以便进行集成测试。

我听过一些关于代码优先和EF 5这种支持的讨论,但我不知道它是否达到了Rails和Django所提供的水平。

当然有可比的东西。 任何信息将不胜感激!

2 个答案:

答案 0 :(得分:13)

在EF5中引入了新概念,称为迁移。您可能过去常常在Rails或Django应用程序中使用类似的东西。

迁移是一个类,它具有多个升级/降级DB版本的功能。

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);
    }
}

如果需要,可以将设置代码移动到基类。

答案 1 :(得分:6)

我开发了一个包含600多个自动集成测试的Entity Framework应用程序。这是我使用的过程:

  • 实体框架代码首次迁移只是为了设置数据库结构(表,索引等)。我不使用迁移来播种数据。

  • 将数据库设置为特定的已知状态的SQL脚本。例如,一个用于插入ASP.NET成员资格用户的脚本;另一个为最相关的表设置样本数据;和其他更具体的场景。脚本通常会从相应的表中删除记录,并以适当的顺序再次插入它们,以避免关系冲突。这些脚本作为嵌入式资源包含在Visual Studio项目中。

  • 一个帮助程序类,它可以通过名称从资源获取脚本并对数据库执行,包括使用“GO”批处理命令。 ConnectionContext.ExecuteNonQuery可用于此。

  • 在整个测试套件的开头,我执行设置用户,权限和其他非常一般环境配置的脚本。

  • 在每个测试方法之前,我会根据需要执行一个或多个脚本,以便在运行的测试所需的上下文中设置数据库。例如,在读取,插入,更新和删除数据的一系列CRUD测试之前,我运行一个脚本,用适当的表为测试数据添加种子。

  • 我假设数据库是在特定的上下文中设置的,我会编写测试用例。例如,对更新操作的测试将尝试检索具有已知密钥的记录,更新它并再次读取以检查它是否在数据库中更新。

尽管SQL脚本不像Rails夹具那样容易编写和读取,但它们非常快并且可以进行任何需要的操作(例如DELETE,INSERT,UPDATE,执行存储过程)。

这项技术在涉及50个数据库表和非常复杂的业务规则和流程的项目中得到了充分证明。它使测试简单而一致。