Testing ASP.NET DbContext in Local Methods

I have an ASP.NET MVC project and I write my service according to this:

public class UserService : IUserService { public void AddUser(UserModel userModel) { if (ModelState.IsValid){ var user = new User { FirstName = userModel.FirstName, LastName = userModel.LastName, Email = userModel.Email, Age = userModel.Age }; using (var context = new MyDbContext()) { context.Users.Add(user); } } } //... More code for service } 

And my DbContext class:

 public class MyDbContext : DbContext { public MyDbContext(): base("name=mydb"){} public DbSet<User> Users {get; set;} //.. More domain objects. } 

This works fine for the most part, but the problem arises when I want to try testing it. I follow the general recommendations here with bullying, but this is only if the DbContext is declared as an instance of the class, as opposed to a function variable. I want to do it like this because it allows me to control the transaction and the deletion of the context. Anyone have any suggestions on how to do this?

My bullying is as follows:

 public class UserServiceTest { [Fact] public void TestAddUser() { var userSet = GetQueryableMockDbSet(userData.ToArray()); var context = new MyDbContext { Users = userSet }; var userService = new UserService(); userService.AddUser(); // HOW DO I GET CONTEXT IN HERE? } private static DbSet<T> GetQueryableMockDbSet<T>(params T[] sourceList) where T : class { var queryable = sourceList.AsQueryable(); var dbSet = new Mock<DbSet<T>>(); dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider); dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression); dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType); dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(queryable.GetEnumerator()); return dbSet.Object; } } 
+5
source share
3 answers

One way to achieve your goal

I want to do it like this because it allows me to control the transaction and the deletion of the context.

It would do something line by line

 public class UserService : IUserService { private ContextFactory _ContextFactory; public UserService(ContextFactory contextFactory) { _ContextFactory = contextFactory; } public void AddUser(UserModel userModel) { ... using (var context = _ContextFactory.CreateInstance()) { context.Users.Add(user); } } 

}

This will allow you to inject different instances of ContextFactory that would create a DbContext using Mock

+2
source

I would definitely prefer the IOC approach, but if you want a quick solution without rewriting too much code, you can do something like this:

 public class UserService : IUserService { public static Func<MyDbContext> CreateContext = () => new MyDbContext(); public UserService () { } public void AddUser(UserModel userModel) { ... using (var context = CreateContext()) { context.Users.Add(user); } } } 

You do not need to change the production code, but in your TestMethod you can do

  var context = new MyDbContext { Users = userSet }; UserService.CreateContext = () => context; 
+1
source

You need to pass the DbContext in the service constructor. The easiest way to do this is to start using any IoC infrastructure (AutoFac, Unity, Ninject, etc.). To mock a database, the easiest way is to start using any mocking library like Moq and RhinoMocks.

 public class UserService : IUserService { private MyDbContext _context; public UserService (MyDbContext dbContext) { _context = dbContext; } } 
0
source

All Articles