Unit testing Entity Framework 6 with IdentityDbContext

I am currently participating in unit tests for Entity Framework 6 operations in ASP.NET Web API 2.0 using the following MSDN tutorial:

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

The tutorial suggests creating an interface to use instead of the DbContext class. This interface is then used throughout the application, allowing controllers to be tested using a "test context".

Below is the proposed interface from the tutorial:

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

Since I use SaveChangesAsync (), I changed the interface below:

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

Unfortunately, this tutorial assumes that the context has a DbContext base class when mine uses IdentityDbContext as its base class (see below). There seems to be no way to call SaveChangesAsync (), which I use instead of SaveChanges (), from my context, without being able to properly implement the interface.

 public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext { public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) { } public Task<int> SaveChangesAsync() { // No way to call DbContext.SaveChangesAsync() from here } } 

Any ideas or suggestions would be much appreciated!

EDIT:

The following are copies of the classes that are currently in use:

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

Example constructor constructor (which uses an interface)

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

EDIT 2:

It seems that there might be a problem with the class hierarchy. Below is another (hopefully related) build error:

 UserManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(db)); Error 2 Argument 1: cannot convert from 'IApplicationDbContext' to 'System.Data.Entity.DbContext' 

For reference, my ApplicationUser class has an IdentityUser base class:

 public class ApplicationUser : IdentityUser 

EDIT 3:

As John mentioned, you should expect an error in EDIT 2. Unfortunately, the error also occurred for the context itself (ApplicationDbContext), and not just for the interface (IApplicationDbContext).

Now the problem is solved, but only by removing and reinstalling packages from the solution, restarting Visual Studio and then restoring the project. I am still not sure of a specific reason.

I noted that John answered correctly, as it would under normal circumstances.

+6
source share
1 answer

According to MSDN, here IdentityDbContext inherited from DbContext., So if you need to call directly, then base.SaveChangesAsync should work.

However, in fact, you do not need to implement this method, since it is already implemented by DbContext in a "real" context, unless you use an explicit implementation of the interface or add more code (which you are not using an example). You need to implement something in TestDbContext, since it will not inherit from DbContext.

If I implement SaveChangesAsync on my own:

 public class ApplicationDbContext : IdentityDbContext<ApplicationUser>, IApplicationDbContext { public Task<int> SaveChangesAsync() { return base.SaveChangesAsync(); // No way to call DbContext.SaveChangesAsync() from here } } 

Then on the assembly, I get this warning:

Warning 1 'SOWorking.ApplicationDbContext.SaveChangesAsync ()' hides the inherited element 'System.Data.Entity.DbContext.SaveChangesAsync ()'. To force the current element to override this implementation, add an override keyword. Otherwise, add a new keyword.

There are no warnings in the assembly if I completely omit the implementation of SaveChangesAsync or add an override as follows:

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

However, if you have nothing to do in SaveChangesAsync , then this is pointless (and Resharper highlights it as such).

+8
source

Source: https://habr.com/ru/post/981051/


All Articles