为什么我的moq db对象没有产生任何结果

4 c# unit-testing entity-framework moq mocking

我有一个moq数据库,其中包含读取序列化实体的json文件的方法,并将它们反序列化为moq dbset.当我设置dbcontext时,一个表具有所有预期结果,而另一个表具有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.
Run Code Online (Sandbox Code Playgroud)

这些是读取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;

        }
Run Code Online (Sandbox Code Playgroud)

当我断开进入'return mockSet'对象并打开结果视图时,数据存在,列表被正确填充,在此处输入图像描述但是如果我将光标移开然后返回到它并展开结果查看数据消失了'枚举没有结果'.如果我甚至没有移动断点,这怎么可能呢?我只是简单地扩展结果视图以查看数据,移动鼠标光标然后再钻回来,在同一实例中,数据消失了.截图提供.

图片1

图2  - 没有结果

Luk*_*brt 10

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

mockSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
Run Code Online (Sandbox Code Playgroud)

此设置为每个GetEnumerator函数调用返回相同的枚举器.枚举项后,枚举器不会再​​为后续调用生成结果.

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

mockSet.As<IQueryable<T>>()
    .Setup(m => m.GetEnumerator()).Returns(() => data.GetEnumerator());
Run Code Online (Sandbox Code Playgroud)

我对显式IEnumerable<T>实现的原始假设是错误的.

DbSet<T>课程没有任何ToList()方法.要将DbSet<T> 列表转换为列表,请IEnumerable<T>.ToList()使用该方法.

该接口IEnumerable<T>DbSet<T>明确实现.所以我认为,你需要设置你Mock<DbSet<T>> 的返回正确的枚举器,即使是IEnumerable<T> 接口.

mockSet.As<IEnumerable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());
Run Code Online (Sandbox Code Playgroud)