【问题标题】:Testing Entity Framework with fixtures使用夹具测试实体框架
【发布时间】:2012-07-04 10:42:35
【问题描述】:

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

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

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

肯定有类似的东西。 任何信息将不胜感激!

【问题讨论】:

  • 我只知道@LadislavMnrka 会喜欢这个。 :)
  • 我相信 AutoFixture 远不是您正在寻找的解决方案,但它是我能找到的最接近 EF 自动化装置的解决方案。
  • 不完全是,EF 允许重新初始化数据库(再次创建它,可能添加数据等),但这不附加到任何测试框架,所有事情都在您重新启动应用程序时完成在 Visual Studio 中。但是,如果需要,您也可以从测试框架中调用此初始化方法
  • 我已经包含了更多关于我如何使用 Entity Framework 应用端到端集成测试来访问实时数据库和执行业务逻辑(没有任何模拟或伪造)的详细信息。我希望它对你有帮助。我不能分享实际代码,因为它是专有的。

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


【解决方案1】:

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

Migration 是一个类,具有升级/降级 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);
    }
}

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

【讨论】:

  • 对于具有许多表且迁移历史较长的数据库,删除数据库并为每个测试类(甚至方法)重新创建它可能会增加您的测试时间。
【解决方案2】:

我使用 Entity Framework 开发了一个应用程序,该应用程序具有 600 多个自动化集成测试。这是我使用的过程:

  • Entity Framework 代码首先迁移只是为了设置数据库结构(表、索引等)。我不使用迁移来播种数据。

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

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

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

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

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

虽然 SQL 脚本不像 Rails 固定装置那样容易编写和读取,但它们非常快并且可以进行任何需要的操作(例如,删除、插入、更新、执行存储过程)。

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

【讨论】:

  • 感谢您的体验
猜你喜欢
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 1970-01-01
  • 2013-10-17
  • 2010-12-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多