简体   繁体   中英

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. 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.

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?

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". 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?

Could anyone explain why the ApplicationUser models require IDbSet, but the CarModels require just DbSet

IdentityDbContext class by design used IDbSet<TEntity> for both Users and Roles properties

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?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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