user1108948
user1108948

Reputation:

How to mock up dbcontext?

I am using Entity Framework 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 class

public 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 the dbContext.

public IsValid(string ID)
{
    var results = _dbContext.Blogs.First(x => x.ID);
    // 
}

Upvotes: 6

Views: 16365

Answers (2)

Brilliant-DucN
Brilliant-DucN

Reputation: 724

Try to add new a constructor without parameter.

public ApplicationDbContext() {}

Upvotes: -1

Nkosi
Nkosi

Reputation: 247088

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

Upvotes: 18

Related Questions