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

时间:2015-11-04 14:30:15

标签: c# entity-framework unit-testing mocking moq

我有一个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.

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

        }

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

Image 1

Image 2 - No Results

1 个答案:

答案 0 :(得分:10)

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

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

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

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

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

我对明确IEnumerable<T>实施的原始假设是错误的。

  

DbSet<T>类没有任何ToList()方法。转换   DbSet<T>方法列表IEnumerable<T>.ToList()   使用

     

接口IEnumerable<T>DbSet<T>类实现   explicitly。我想,您需要设置Mock<DbSet<T>>   即使IEnumerable<T>也返回正确的枚举器   接口

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