简体   繁体   English

如何使用IdentityDbContext模拟实体框架?

[英]How to mock Entity Framework using IdentityDbContext?

I am working on an ASP.NET MVC web app with individual authentication to store details about users cars. 我正在使用个人身份验证来存储有关用户汽车的详细信息的ASP.NET MVC Web应用程序。 I will need to unit test the web app by mocking the entity framework, thus I have read I will need to implement an interface for the ApplicationDbContext class. 我将需要通过模拟实体框架对Web应用程序进行单元测试,因此我已阅读到将需要为ApplicationDbContext类实现一个接口。

This is my first attempt at using entity framework and I just wanted to check whether my ApplicationDbContext class and interface will be suitable for mocking the framework when unit testing? 这是我使用实体框架的第一次尝试,我只是想检查单元测试时,我的ApplicationDbContext类和接口是否适合模拟框架?

public interface IApplicationDbContext : IDisposable
{
    IDbSet<ApplicationUser> Users { get; set; }
    DbSet<CarModel> Cars { get; set; }
    int SaveChanges();
    void MarkAsModified(CarModel car);
}

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

    public static ApplicationDbContext Create()
    {
        return new ApplicationDbContext();
    }

    public DbSet<CarModel> Cars { get; set; }

    public override IDbSet<ApplicationUser> Users { get; set; }

    public void MarkAsModified(CarModel car)
    {
        Entry(car).State = EntityState.Modified;
    }
}

Some of the classes were formed by autocorrect using Visual Studios "Quick Actions". 其中一些类是使用Visual Studios“快速操作”通过自动更正形成的。 Could anyone explain why the ApplicationUser models require IDbSet , but the CarModels require just DbSet , and why the Users in the ApplicationDbContext class require an override? 谁能解释为什么ApplicationUser模型需要IDbSet ,而CarModels只需要DbSet ,为什么ApplicationDbContext类中的Users需要重写?

Could anyone explain why the ApplicationUser models require IDbSet, but the CarModels require just DbSet 谁能解释为什么ApplicationUser模型需要IDbSet,而CarModels仅需要DbSet

IdentityDbContext class by design used IDbSet<TEntity> for both Users and Roles properties 根据设计, IdentityDbContext类IDbSet<TEntity>用于UsersRoles属性

public virtual IDbSet<TUser> Users { get; set; }
public virtual IDbSet<TRole> Roles { get; set; }

In your case you can follow the same pattern 在您的情况下,您可以遵循相同的模式

public virtual IDbSet<CarModel> Cars { get; set; }

and update your interface to match as well 并更新您的界面以使其匹配

public interface IApplicationDbContext : IDisposable {
    IDbSet<ApplicationUser> Users { get; set; }
    IDbSet<CarModel> Cars { get; set; }
    int SaveChanges();
    void MarkAsModified(CarModel car);
}

The interface can then be safely mocked for your isolated unit tests, provided the interface was being injected into the subject under test. 如果接口已被注入到测试对象中,则可以安全地模拟该接口进行隔离的单元测试。

and why the Users in the ApplicationDbContext class require an override? 以及为什么ApplicationDbContext类中的Users需要重写?

It does not actually need to be overridden as the generic nature of the class (ie IdentityDbContext<ApplicationUser> ) would already make the property follow the provided ApplicationUser type. 实际上,不需要重写它,因为该类的通用性质(即IdentityDbContext<ApplicationUser> )已经使该属性遵循提供的ApplicationUser类型。 You could have just as easily left it out. 您可以轻松地将其省略。

public class ApplicationDbContext 
    : IdentityDbContext<ApplicationUser>, IApplicationDbContext {

    public ApplicationDbContext()
        : base("ApplicationDb", throwIfV1Schema: false) {
    }

    public static ApplicationDbContext Create() {
        return new ApplicationDbContext();
    }

    public virtual IDbSet<CarModel> Cars { get; set; }

    public void MarkAsModified(CarModel car) {
        Entry(car).State = EntityState.Modified;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM