简体   繁体   中英

Why is my moq db object yielding no results

I have a moq database with methods that read a json file of serialized entities and deserializes them into a moq dbset. When I set up the dbcontext one table has all the expected results whereas the other table has 0 results. My Json file is properly formatted and verified and has 5 entries.

    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.

These are the methods that read the json file and deserializes them into 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;

        }

When I breakpoint into the 'return mockSet' object and open up the Results View the data is present, the list is correctly populated,enter image description here however if I move the cursor away and then go back into it and expand the Results View the data is gone with the 'Enumeration yielded no results'. How is this possible if I've not even moved the breakpoint. I've literaly simply expanded the results view to see the data, moved my mouse cursor away and then drilled back in, in the same instance, and the data is gone. Screenshot provided.

图片1

图2  - 没有结果

The actual problem is in the way the mock is initialized.

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

This setup returns the same enumerator for every GetEnumerator function call. Once items are enumerated, the enumerator yields no more results for subsequent calls.

The setup needs to be modified to use a lambda expression. That way, for every GetEnumerator function call a new instance of the enumerator is returned.

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

My original assumption about the explicit IEnumerable<T> implementation was wrong.

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()); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM