使用IdentityDbContext对Entity Framework 6进行单元测试

时间:2015-01-15 13:12:12

标签: c# entity-framework unit-testing asp.net-web-api asp.net-identity

我目前正在使用以下MSDN教程在ASP.NET Web API 2.0应用程序中为Entity Framework 6操作添加单元测试:

http://msdn.microsoft.com/en-us/data/dn314431

本教程建议创建一个接口来代替应用程序的DbContext类。然后在整个应用程序中使用该接口,允许使用“模拟”控制器对控制器进行测试。测试环境。

以下是教程中建议的界面:

public interface IBloggingContext 
{ 
    DbSet<Blog> Blogs { get; } 
    DbSet<Post> Posts { get; } 
    int SaveChanges(); 
}

当我使用SaveChangesAsync()时,我已将界面修改为以下界面:

public interface IApplicationDbContext : IDisposable
{
    DbSet<Blog> Blogs { get; } 
    DbSet<Post> Posts { get; } 
    Task<int> SaveChangesAsync();
}

不幸的是,当我使用IdentityDbContext作为其基类时,本教程假设上下文具有DbContext的基类(参见下文)。似乎无法从我的上下文调用SaveChangesAsync() - 我正在使用它来代替SaveChanges(),这使得它无法正确实现接口。

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {

    }

    public Task<int> SaveChangesAsync()
    {
        // No way to call DbContext.SaveChangesAsync() from here
    }
}

非常感谢任何想法或建议!

修改

以下是目前正在使用的类的副本:

ApplicationDbContext

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
{
    public ApplicationDbContext()
        : base("DefaultConnection", throwIfV1Schema: false)
    {

    }

    public Task<int> SaveChangesAsync()
    {
        // Cannot resolve base.SaveChangesAsync() from here
    }

    public DbSet<Product> Products { get; set; }
}

IApplicationDbContext

public interface IApplicationDbContext
{
    Task<int> SaveChangesAsync();
    DbSet<Product> Products { get; set; }
}

示例Controller Constructor (使用界面)

protected BaseEntityController(IApplicationDbContext context)
{
    db = context;
}

编辑2:

看起来类层次结构可能存在问题。下面是另一个(希望是相关的)构建错误:

UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db));

Error   2   Argument 1: cannot convert from 'IApplicationDbContext' to 'System.Data.Entity.DbContext'

作为参考,我的ApplicationUser类有一个基类IdentityUser:

public class ApplicationUser : IdentityUser

编辑3:

如Jon所述,EDIT 2中发布的错误是预料之中的。不幸的是,上下文本身(ApplicationDbContext)也出现了错误,而不仅仅是接口(IApplicationDbContext)。

此问题现已解决,但只能从解决方案中卸载并重新安装软件包,重新启动Visual Studio,然后重建项目。我仍然不确定问题的确切原因。

我将Jon的答案标记为正确,就像在正常情况下一样。

1 个答案:

答案 0 :(得分:8)

根据MSDN here IdentityDbContext继承自DbContext。,所以如果您需要直接调用,那么base.SaveChangesAsync应该有效。

但是,实际上您并不需要实施该方法,因为它已经由DbContext在&#34; real&#34;中实现了。上下文除非您使用显式接口实现或添加更多代码(您不在示例中)。你需要在TestDbContext中实现一些东西,因为它不会从DbContext继承。

如果我按照您的意愿实施SaveChangesAsync

public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext
{
    public Task<int> SaveChangesAsync()
    {
        return base.SaveChangesAsync();

        // No way to call DbContext.SaveChangesAsync() from here
    }
}

然后在构建中我收到此警告:

  

警告1&#39; SOWorking.ApplicationDbContext.SaveChangesAsync()&#39;隐藏继承成员&#39; System.Data.Entity.DbContext.SaveChangesAsync()&#39;。要使当前成员覆盖该实现,请添加override关键字。否则添加新关键字。

如果我要完全省略SaveChangesAsync的实现,或者像这样添加覆盖,那么构建没有警告:

public override Task<int> SaveChangesAsync()
{
    return base.SaveChangesAsync();
}

但是,除非你在SaveChangesAsync中有任何其他事情要做,否则这是毫无意义的(并且Resharper会为你提供灰色的东西)。