如何使用 Entity Framework Code First V6.1.2 进行集成测试

Posted

技术标签:

【中文标题】如何使用 Entity Framework Code First V6.1.2 进行集成测试【英文标题】:How to do integration test using Entity Framework Code First V6.1.2 【发布时间】:2015-04-15 10:36:27 【问题描述】:

我正在尝试使用 EF 代码优先 6.1.2 为我的数据库访问逻辑添加一些集成测试。我想在一个单独的数据库上执行此操作,以免我的生产数据库与测试数据混淆。

此外,测试应该是可重复的,这意味着如果数据库不存在,则应创建数据库、播种测试数据、运行测试并最终在完成后将其删除。

如果没有测试数据库的Enable-Migrations 命令,我也看不出如何做到这一点。

这将是我的dbContext 用于生产:

public partial class ApplicationDbContext : 
        IdentityDbContext<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>, IApplicationDbContext

    public ApplicationDbContext() : base("name=DefaultConnection")  

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    
        if (base.Database.Connection.ConnectionString == "DefaultConnectionTest")
            Database.SetInitializer(new DropCreateDatabaseAlways<ApplicationDbContext>());
        else
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());

        base.OnModelCreating(modelBuilder);

        modelBuilder.Entity<ApplicationUser>().ToTable("Users");
        modelBuilder.Entity<ApplicationRole>().ToTable("Roles");
        modelBuilder.Entity<ApplicationUserRole>().ToTable("UserRoles");
        modelBuilder.Entity<ApplicationUserLogin>().ToTable("UserLogins");
        modelBuilder.Entity<ApplicationUserClaim>().ToTable("UserClaims");
    

    public DbSet<Order> Orders  get; set; 
    public DbSet<Product> Products  get; set; 
    public DbSet<Person> Persons  get; set; 

我使用来自NinjectDependency Injection 进行了所有设置。 添加一个带有连接字符串作为参数public ApplicationDbContext(string dbConnection) : base(dbConnection) 的额外构造函数,仍然会让我运行Enable-Migrations 命令。

有没有办法自动化这个过程?或者任何人都可以提出其他建议?

我想坚持使用 SQL Server 数据库,因为使用不同的数据库进行测试可能会给我带来误报。

【问题讨论】:

【参考方案1】:

您必须使用数据库初始化程序。有几个可用的:

Database.SetInitializer(new CreateDatabaseIfNotExists<InterstoneContext>());
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<InterstoneContext>());
Database.SetInitializer(new DropCreateDatabaseAlways<InterstoneContext>());

您需要第三个选项。请注意不要覆盖生产数据库。

【讨论】:

我知道我需要使用哪个初始化程序,但是 Enable-Migrations 对测试数据库有什么影响?您在我的问题中看到的初始化程序用于生产数据库。 我不明白你的意思,我以为你不想迁移。第三个选项总是会创建一个新数据库,如果需要,您可以在其中播种测试数据。 这不是我想要的,我的印象是代码首先必须启用迁移。你说这没必要?我将如何传递连接字符串以用于第三个选项? 不,您不必启用迁移。您如何传递连接字符串取决于您的实现。在您的情况下,您需要向 ApplicationDbContext 类添加一个字符串,这样您就可以为您的测试传递一个与用于生产的字符串不同的字符串。我正在使用统一,因此即使对于连接字符串,我也更依赖依赖注入。 我也有 DI 设置,但我使用的是 Ninject。我添加了一个额外的构造函数,它接受一个连接字符串,在我的问题中查看我的代码。另外,我刚刚尝试了您的方法,运行测试时没有创建测试数据库。结果如下:The underlying provider failed on Open. ---&gt; System.Data.SqlClient.SqlException: Cannot open database "DefaultConnectionTest" requested by the login。希望你能指导我完成这项工作。

以上是关于如何使用 Entity Framework Code First V6.1.2 进行集成测试的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Entity Framework 7 记录查询?

Entity Framework 学习系列 - 认识理解Entity Framework

如何使用 Entity Framework Core 模拟异步存储库

如何使用 Entity Framework 生成和自动递增 Id

如何使用 Entity Framework Core 正确保存 DateTime?

如何使用 Entity Framework Core 获取主键值