如何模拟dbcontext?

时间:2016-06-04 13:03:06

标签: c# entity-framework unit-testing moq

我在.net core 1.0 rc2中使用Entity Framework 7。这是班级。

public class ApplicationDbContext : DbContext
{
    public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options)
    {

    }
    public DbSet<Blog> Blogs { get; set; }
}

然后将ApplicationDbContext注入类

public class BtnValidator
{
    private readonly ApplicationDbContext _dbContext;
    public BtnValidator(ApplicationDbContext dbContext)
    {
        _dbContext = dbContext;
    }
}

不确定如何在单元测试方法中模拟它。

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

修改

BtnValidator中,我有代码可以访问dbContext

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

1 个答案:

答案 0 :(得分:13)

你可以抽象你的DbContext让它变得可以模仿。

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

然后,您可以将合同注入依赖类

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

然后在你的单元测试中你可以模拟接口

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