为什么我的最小起订量数据库对象没有产生任何结果
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());
我有一个最小起订量数据库,其中包含读取序列化实体的 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 anyToList()
method. To convert theDbSet<T>
to a list theIEnumerable<T>.ToList()
method is used.The interface
IEnumerable<T>
is implemented by theDbSet<T>
class explicitly. So I think, you need to setup yourMock<DbSet<T>>
to return the correct enumerator even for theIEnumerable<T>
interface.mockSet.As<IEnumerable<T>>().Setup(m => m.GetEnumerator()).Returns(data.GetEnumerator());