繁体   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