How to mock up dbcontext?
You could abstract your DbContext to make it mockable.
public interface IDbContext {
DbSet<Blog> Blogs { get; set; }
//...other properties and members needed for db context
int SaveChanges();
}
public class ApplicationDbContext : DbContext, IDbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) {
}
public DbSet<Blog> Blogs { get; set; }
}
You can then inject the contract into dependent classes
public class BtnValidator {
private readonly IDbContext _dbContext;
public BtnValidator(IDbContext dbContext) {
_dbContext = dbContext;
}
public bool IsValid(string ID) {
var result = _dbContext.Blogs.FirstOrDefault(x => x.ID == ID);
return result != null;
}
}
and then in your unit tests you can mock the interfaces
[Fact]
public void Ensure_Proper_Btn_Validated_Return_True() {
//Arrange
var id = "1234"
var blogsTestData = new List<Blog>(){ new Blog { ID = id } };
var blogs = MockDbSet(blogsTestData);
//Set up mocks for db sets
var dbContext = new Mock<IDbContext>();
dbContext.Setup(m => m.Blogs).Returns(blogs.Object);
var validator = new BtnValidator(dbContext.Object);
//Act
var results = validator.IsValid(id);
//Assert
Assure.True(results);
}
Mock<DbSet<T>> MockDbSet<T>(IEnumerable<T> list) where T : class, new() {
IQueryable<T> queryableList = list.AsQueryable();
Mock<DbSet<T>> dbSetMock = new Mock<DbSet<T>>();
dbSetMock.As<IQueryable<T>>().Setup(x => x.Provider).Returns(queryableList.Provider);
dbSetMock.As<IQueryable<T>>().Setup(x => x.Expression).Returns(queryableList.Expression);
dbSetMock.As<IQueryable<T>>().Setup(x => x.ElementType).Returns(queryableList.ElementType);
dbSetMock.As<IQueryable<T>>().Setup(x => x.GetEnumerator()).Returns(() => queryableList.GetEnumerator());
dbSetMock.Setup(x => x.Create()).Returns(new T());
return dbSetMock;
}
Undo
Stack Overflow moderator. I bite, but only when sufficiently provoked. Everything I post on Stack Overflow is licensed to you under CC0: you can copy, modify, distribute and perform the work, even for commercial purposes, all without asking permission. Feel free to just throw it into your project without attribution. That's what most folks do anyway... but for my contributions, it's nice and legal.
Updated on June 07, 2022Comments
-
Undo almost 2 years
I am using Entity Framework 7 in .net core 1.0 rc2. Here is the class.
public class ApplicationDbContext : DbContext { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } public DbSet<Blog> Blogs { get; set; } }
Then inject the
ApplicationDbContext
to a classpublic class BtnValidator { private readonly ApplicationDbContext _dbContext; public BtnValidator(ApplicationDbContext dbContext) { _dbContext = dbContext; } }
Not sure how to mock it in unit test method.
[Fact] public void Ensure_Proper_Btn_Validated_Return_True() { var dbContext = mockup(ApplicationDbContext); //how var validator = new BtnValidator(dbContext); var results = validator.IsValid("1234"); Assure.True(results); }
EDIT
In
BtnValidator
, I have code to access thedbContext
.public IsValid(string ID) { var results = _dbContext.Blogs.First(x => x.ID); // }
-
Evk almost 8 yearsIt's not a mock, but consider using in-memory provider for EF (Effort - effort.codeplex.com). Good for unit-testing EF-related code.
-
Admin almost 8 years@Evk, there are two things. One is I need unit test, Secondly I use .Net core 1.0 rc2, the library perhaps doesn't support it.
-
Crowcoder almost 8 yearsMaybe it is not practical for you at this point but consider using a repository pattern. Then you mock the repo, not the actual db access.
-
RBT almost 8 years@Crowcoder We use unit of work pattern which wraps the repositories behind the scene corresponding to various tables of my database. For testing scenarios we have a separate class in the name of InMemoryUnitOfWork which acts in place of real UnitOfWork class to manage all the repositories in-memory. In-memory repositories have no dependencies on real database.
-
-
farizmamad over 2 yearsGreat idea. If I'm not mistaken, Mock is provided in Moq Nuget package. However, in my case x.Create() method doesn't found. I installed Moq v4.16.1