簡體   English   中英

在實體框架6.1中模擬DbContext

[英]Mocking DbContext in Entity Framework 6.1

我發現許多示例(顯然)顯示了使用EF 6模擬DbContext的清晰工作示例,但是,似乎沒有一個對我有用,我也不完全知道為什么。

這是設置模擬的我的單元測試代碼;

var mockData = new List<User> { new User { Email = "my@email.com", Id = 1 } }.AsQueryable();

var mockSet = new Mock<DbSet<User>>();
    mockSet.As<IQueryable<User>>().Setup(m => m.Provider).Returns(mockData.Provider);
    mockSet.As<IQueryable<User>>().Setup(m => m.Expression).Returns(mockData.Expression);
    mockSet.As<IQueryable<User>>().Setup(m => m.ElementType).Returns(mockData.ElementType);
    mockSet.As<IQueryable<User>>().Setup(m => m.GetEnumerator()).Returns(mockData.GetEnumerator());

    var mockContext = new Mock<MyDbContext>();
    mockContext.Setup(c => c.Users).Returns(mockSet.Object);

然后調用我正在測試的服務;

var service = new UsersService(mockContext.Object);

var user = service.GetById(1);

由於基礎DbSet始終為null,因此將引發NullReferenceException。 該代碼執行以下操作;

在BaseClass中;

public IEnumerable<T> GetAll()
{
    return _dbSet.AsEnumerable();
}

在子類中;

  public User GetById(int id)
        {
            return GetAll().FirstOrDefault(x => x.Id == id);
        }

請注意,盡管關於SO的其他問題似乎與之相關,但它們並未涵蓋EF 6。

作為參考,這是MSDN文章,該文章對相同的代碼進行了修改以使其能夠編譯。

https://msdn.microsoft.com/zh-CN/data/dn314429.aspx

編輯:

降低了UserService的復雜性(它使用泛型/接口),現在的代碼很簡單;

public User GetById(int id)
        {
            return _dbContext.Set<User>().FirstOrDefault(x => x.Id == id);
        }

如果我將其進一步更改為;

   var dbSet = _dbContext.Set<User>();
        return dbSet.FirstOrDefault(x => x.Id == id);

我可以清楚地看到dbSet為null。

編輯2

根據wablab的建議,似乎模擬.Set解決了該問題。

還應感謝Vladyslav Kushnir的DbSet通用方法。

適用於可能需要它的任何人的工作代碼;

 private static Mock<DbSet<T>> GetDbSetMock<T>(IEnumerable<T> items = null) where T : class
        {
            if (items == null)
            {
                items = new T[0];
            }

            var dbSetMock = new Mock<DbSet<T>>();
            var q = dbSetMock.As<IQueryable<T>>();

            q.Setup(x => x.GetEnumerator()).Returns(items.GetEnumerator);

            return dbSetMock;
        }



var mockContext = new Mock<Model1>();

var users = new List<User> { new User { Email = "my@email.com", Id = 1 } };

mockContext.Setup(x => x.Set<User>()).Returns(GetDbSetMock(users).Object);

var service = new UsersService(mockContext.Object);

var user = service.GetById(1);

我認為您需要在Set<User>()方法上創建一個設置來返回您的模擬。

    private Mock<DbSet<T>> GetDbSetMock<T>(IEnumerable<T> items = null) where T : class
    {
        if (items == null)
        {
            items = new T[0];
        }

        var dbSetMock = new Mock<DbSet<T>>();
        var q = dbSetMock.As<IQueryable<T>>();

        q.Setup(x => x.GetEnumerator()).Returns(items.GetEnumerator);

        return dbSetMock;
    }

這是我用來模擬DbContext的DbSet的工作得很好的通用方法。 該方法的實際調用是:

var contextMock = new Mock<MyContext>();
contextMock.Setup(x => x.MyDbEntities).Returns(GetDbSetMock<MyDbEntity>().Object);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM