簡體   English   中英

從DbContext訪問Moq Mock數據兩次調用時消失了嗎?

[英]Accessing Moq Mock Data from DbContext disappears when called twice?

我試圖了解我的應用程序中正在發生的行為。 我已經DbContext了我的DbContext ,當我進行調用時,從dbContext.Set<T>().ToList()獲取項目,第二次調用不包含我的模擬數據。 我不確定為什么會發生這種情況,因為該數據應該仍然存在。 請參見下面的代碼:

SUT:

public class Employee
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    public decimal Salary { get; set; }
}

public class EmployeeDb
    : DbContext
{
    public EmployeeDb()
    {

    }

    public virtual IDbSet<Employee> Employees { get; set; }
}

單元測試:

public class MockDatabase
{
    public Mock<EmployeeDb> SetMockData()
    {
        var mockDb = new Mock<EmployeeDb>();

        mockDb.Setup(i => i.Set<Employee>()).Returns(GetMockSet(Employees).Object);
        mockDb.SetupGet(i => i.Employees).Returns(() => GetMockSet(Employees).Object);

        return mockDb;
    }
    private List<Employee> _providers;
    private List<Employee> Employees => _providers ?? (_providers = new List<Employee>
    {
        GetEmployee(1),
        GetEmployee(2),
        GetEmployee(3),
        GetEmployee(4),
        GetEmployee(5),
    });
    private static Employee GetEmployee(int id)
    {
        return new Employee
        {
            FirstName = Faker.Name.First(),
            LastName = Faker.Name.Last(),
            Age = Faker.RandomNumber.Next(50),
            Id = id,
            Salary = Faker.RandomNumber.Next(100000)
        };
    }

    #region Hood

    public static Mock<DbSet<T>> GetMockSet<T>(IList<T> items) where T : class
    {
        var querable = items.AsQueryable();
        var mockSet = new Mock<DbSet<T>>();
        mockSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(querable.Provider);
        mockSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(querable.Expression);
        mockSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(querable.ElementType);
        mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(querable.GetEnumerator());
        mockSet.Setup(i => i.Add(It.IsAny<T>())).Callback(delegate (T item) {
            items.Add(item);
        });
        return mockSet;
    }

    #endregion
}


[TestClass]
public class UnitTest1
{
    private EmployeeDb _context;

    [TestInitialize]
    public void TestInitialize()
    {
        var mockDb = new MockDatabase();
        _context = mockDb.SetMockData().Object;
    }
    [TestMethod]
    public void Test_CallTwice_ReturnsEqualCount()
    {
        var emps = _context.Set<Employee>().ToList();
        var emps2 = _context.Set<Employee>().ToList();

        Assert.IsTrue(emps.Count == emps2.Count);

        // -- This works
        //var empCount = _context.Set<Employee>().Count();
        //var empCount2 = _context.Set<Employee>().Count();

        //Assert.IsTrue(empCount == empCount2);
    }
}

我有沒有關於此代碼的東西嗎? Moq與ToList()嗎?

ToList在調用時枚舉集合,但枚舉器僅向前,因此在第一次調用之后,它已經在末尾。

設置GetEnumerator使用Returns函數的重載,以允許其他方式的多次調用,每次都會返回同一枚舉數,並且您會獲得所遇到的行為。

mockSet.As<IQueryable<T>>()
    .Setup(m => m.GetEnumerator())
    .Returns(() => querable.GetEnumerator()); //<-- function

暫無
暫無

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

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