簡體   English   中英

單元測試通用存儲庫“查找”方法-MSTest,Moq,EF6

[英]Unit Testing Generic Repository “Find” Method - MSTest, Moq, EF6

我對單元測試和Moq相當陌生,但是我嘗試使用Moq和MSTest為通用存儲庫設置單元測試。 我敢肯定,很多事情我可能做錯了,但是我確實可以在測試通用存儲庫中基於表達式的參數時使用幫助。 具體來說,我似乎無法讓模擬的存儲庫返回預期的對象列表,這是代碼:


內容:

public class OrderContext : DbContext, IDisposable
{
    public virtual DbSet<Order> Orders { get; set; }

    public virtual void Commit()
    {
        base.SaveChanges();
    }

}


儲存庫接口/儲存庫

public interface IRepository<T> where T : class
{
    IEnumerable<T> GetManyBySearch(Func<T, bool> where);
}

public class RepositoryBase<T> : IRepository<T> where T : class
{
    private OrderContext _db;
    private DbSet<T> _dbSet;

    public RepositoryBase(OrderContext db) 
    {
        _db = db;
        _dbSet = _db.Set<T>();
    }

    // Get many records by search
    public virtual IEnumerable<T> GetManyBySearch(Func<T, bool> where)
    {
        return _dbSet.Where(where).AsQueryable();
    }
}


...在我的單元測試中,理想情況下,我將能夠設置與測試類似的測試,只是我想讓我的存儲庫根據傳遞給GetManyBySearch的表達式返回內存對象數據的子集() 方法。 當前,我的模擬存儲庫將返回整個數據集,而不管傳遞的是什么表達式 這是示例:


單元測試

    [TestMethod]
    [TestCategory("Repository Tests")]
    public void Order_Get_Many_By_Search()
    {

        Mock<OrderContext> mockDb = new Mock<OrderContext>();
        Mock<RepositoryBase<Order>> mockRepo = new Mock<RepositoryBase<Order>>(mockDb.Object);


        var data = new List<Order>()
        {
            new Order { OrderId = 1, OrderNumber = 111, OrderDate = DateTime.Now },
            new Order { OrderId = 2, OrderNumber = 222, OrderDate = DateTime.Now },
            new Order { OrderId = 3, OrderNumber = 222, OrderDate = DateTime.Now }
        }.AsQueryable();

        var expectedResults = data.Where(m => m.OrderNumber == 222);

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

        mockDb.Setup(m => m.Set<Order>()).Returns(mockSet.Object);

        mockRepo.Setup(m => m.GetManyBySearch(It.IsAny<Func<Order, bool>>()))
            .Returns(mockSet.Object.AsQueryable());

        List<Order> results = mockRepo.Object.GetManyBySearch(m => m.OrderNumber == 222).ToList(); // This returns the entire "data" dataset

        mockRepo.Verify(m => m.GetManyBySearch(It.IsAny<Func<Order, bool>>()), Times.Once());

        Assert.AreEqual(2, results.Count()); // This fails :(
    }


任何幫助將不勝感激。 提前致謝。

我懷疑測試在指示的行上失敗,因為您的樣本數據包含3個元素,並且您斷言它包含2:

var data = new List<Order>()
    {
        new Order { OrderId = 1, OrderNumber = 111, OrderDate = DateTime.Now },
        new Order { OrderId = 2, OrderNumber = 222, OrderDate = DateTime.Now },
        new Order { OrderId = 3, OrderNumber = 222, OrderDate = DateTime.Now }
    }.AsQueryable();

// <snip>...

Assert.AreEqual(2, results.Count()); 

但是,這里更大的問題是在示例中,您實際上是在模擬要測試的方法:

Mock<RepositoryBase<Order>> mockRepo = new Mock<RepositoryBase<Order>>(mockDb.Object);

// <snip>...

List<Order> results = mockRepo.Object.GetManyBySearch(m => m.OrderNumber == 222).ToList();

因此,您無需測試任何生產代碼。 取而代之的是,您只是在測試模擬對象將執行告訴它們的操作。

用實際實例替換模擬存儲庫,然后將所有其他模擬對象注入其中。 然后,這將是對GetManyBySearch方法返回您期望的良好測試。

暫無
暫無

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

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