为什么我的最小起订量数据库对象没有产生任何结果

Why is my moq db object yielding no results

我有一个最小起订量数据库,其中包含读取序列化实体的 json 文件并将它们反序列化为最小起订量数据库集的方法。当我设置 dbcontext 时,一个 table 具有所有预期结果,而另一个 table 具有 0 个结果。我的 Json 文件格式正确并经过验证,有 5 个条目。

    var airportLocationMoq = GetMockDbSet<Repository.Location>(@"Files/ObjectJson/Airports.json");
    var storageAreaMoq = GetMockDbSet<Repository.StorageArea>(@"Files/ObjectJson/StorageAreas.json");
    var dbContext = new Mock<DbContext>();
    dbContext.Setup(x => x.Locations).Returns(airportLocationMoq.Object);
    dbContext.Setup(x => x.StorageAreas).Returns(storageAreaMoq.Object);

    var airportsFromDb = dbContext.Object.Locations.Where(x => x.Type == 1).ToList();
    var storageAreasFromDb = dbContext.Object.StorageAreas.ToList(); //<-this results in 0 entries however there should be 5.

这些是读取 json 文件并将其反序列化为 moq dbset 的方法:

public string LoadFile(string path)
        {
            return File.ReadAllText(path);
        }

        public List<T> GetData<T>(string path)
        {
            string json = LoadFile(path);
            var dataList = JsonConvert.DeserializeObject<List<T>>(json);

            return dataList;
        }

        public Mock<DbSet<T>> GetMockDbSet<T>(string path) where T : class
        {
            var data = GetData<T>(path).AsQueryable();

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

            return mockSet;

        }

当我断点进入 'return mockSet' 对象并打开结果视图时,数据存在,列表已正确填充,但如果我将光标移开然后返回,请在此处输入图像描述并展开结果视图,数据随 'Enumeration yielded no results' 一起消失了。如果我什至没有移动断点,这怎么可能。我只是简单地扩展了结果视图以查看数据,将鼠标光标移开然后再钻回,在同一实例中,数据消失了。提供了屏幕截图。

实际问题在于模拟的初始化方式。

mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());

这为每个 GetEnumerator 函数调用设置 returns 相同的枚举器。枚举项目后,枚举器不会为后续调用产生更多结果。

需要修改设置以使用 lambda 表达式。这样,对于每个 GetEnumerator 函数调用,都会返回枚举器的一个新实例。

mockSet.As<IQueryable<T>>()
    .Setup(m => m.GetEnumerator()).Returns(() => data.GetEnumerator());

我最初关于显式 IEnumerable<T> 实施的假设是错误的。

The DbSet<T> class doesn't have any ToList() method. To convert the DbSet<T> to a list the IEnumerable<T>.ToList() method is used.

The interface IEnumerable<T> is implemented by the DbSet<T> class explicitly. So I think, you need to setup your Mock<DbSet<T>> to return the correct enumerator even for the IEnumerable<T> interface.

mockSet.As<IEnumerable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());