如何从模拟对象中 return IQueryable<TEntity> 对象?
How can I return IQueryable<TEntity> object from a mock object?
我试图将模拟对象 _portalUserRepositoryMock
上的方法 GetAll()
告诉 return 类型 IQueryable<TEntity>
的对象。我知道是这种类型,因为class中的方法要测试return是这种类型。
我一直想不出解决办法。
我在我的项目中看到了这个 , but had errors trying to include the library。关于 Microsoft.EntityFrameworkCore 版本的问题 - 这导致了更多问题。
我为得到这个错误所做的是:
_portalUserRepositoryMock = Substitute.For<IPortalUserRepository>();
_portalUserRepositoryMock.GetAll().Returns(fakeQueryablePUser.AsQueryable());
测试中的 class 使用这样的存储库:
var portal = await _portalUserRepository.GetAll().Include(p =>
p.Portal).Where(p => p.UserId == user.Id && p.Portal.PortalType ==
dto.PortalType).FirstOrDefaultAsync();
而GetAll()
方法是:
public IQueryable<TEntity> GetAll()
{
try
{
return DbContext.Set<TEntity>().AsNoTracking();
}
catch (Exception ex)
{
throw ex;
}
}
我收到这个错误:
Message: System.InvalidOperationException : The provider for the source
IQueryable doesn't implement IAsyncQueryProvider. Only providers that
implement IEntityQueryProvider can be used for Entity Framework
asynchronous operations.
我想我收到此错误是因为正在使用 FirstOrDefaultAsync()
。就是不知道怎么解决。
编辑:
我现在已经能够将 MockQueryable 库添加到我的测试项目中(通过使用版本 1.0.4 而不是最新的 1.1.0 )。我已经按照步骤操作了,如下图:
var fakePortalUser = new PortalUser()
{
PortalId = new Guid()
};
var fakeQueryablePUser = new List<PortalUser>
{
fakePortalUser
}.AsQueryable().BuildMock();
现在最后一步是使用 GetQueryable()
。我在这里尝试使用:
_portalUserRepositoryMock.GetAll().GetQueryable().Returns(fakeQueryablePUser);
但是我在 GetQueryable()
方法调用下看到了红色波浪线。所以代码无法编译。
你不知道,IQueryable<T>
是由 Entity Framework / Core 处理的实现细节。除非您的业务逻辑实际上创建了 IQueryable<T>
的实现,否则您想要 return 模拟存根对象。
即(请注意,这使用库 Moq
来模拟对象,因为我不确定您使用的是什么,并且实现可能会有所不同。)
_mockedEntityQuery = new Mock<IQueryable<T>>();
_portalUserRepositoryMock = Substitute.For<IPortalUserRepository>();
_portalUserRepositoryMock.GetAll().Returns(_mockedEntityQuery.Object);
如果您 return IQueryable<T>
的一个实例,您还将测试该实现,该实现已由 EF 单元测试完成。单元测试应该只测试单元范围内的代码。
最初的问题与您怀疑的 FirstOrDefaultAsync
一样。该扩展期望可查询对象也有一个 IAsyncQueryProvider
以匹配默认情况下模拟不会出现的异步 EF。
删除 .GetQueryable()
,因为您不需要它。该成员来自其中一个演示如何使用模拟库的示例。
还要确保假数据中的数据与 Where
中的谓词相匹配。
.Where(p => p.UserId == user.Id && p.Portal.PortalType == dto.PortalType)
如果没有要枚举的元素,FirstOrDefault
将 return null。
如果数据不满足过滤器,您将默认返回 null。
我试图将模拟对象 _portalUserRepositoryMock
上的方法 GetAll()
告诉 return 类型 IQueryable<TEntity>
的对象。我知道是这种类型,因为class中的方法要测试return是这种类型。
我一直想不出解决办法。
我在我的项目中看到了这个
我为得到这个错误所做的是:
_portalUserRepositoryMock = Substitute.For<IPortalUserRepository>();
_portalUserRepositoryMock.GetAll().Returns(fakeQueryablePUser.AsQueryable());
测试中的 class 使用这样的存储库:
var portal = await _portalUserRepository.GetAll().Include(p =>
p.Portal).Where(p => p.UserId == user.Id && p.Portal.PortalType ==
dto.PortalType).FirstOrDefaultAsync();
而GetAll()
方法是:
public IQueryable<TEntity> GetAll()
{
try
{
return DbContext.Set<TEntity>().AsNoTracking();
}
catch (Exception ex)
{
throw ex;
}
}
我收到这个错误:
Message: System.InvalidOperationException : The provider for the source IQueryable doesn't implement IAsyncQueryProvider. Only providers that implement IEntityQueryProvider can be used for Entity Framework asynchronous operations.
我想我收到此错误是因为正在使用 FirstOrDefaultAsync()
。就是不知道怎么解决。
编辑: 我现在已经能够将 MockQueryable 库添加到我的测试项目中(通过使用版本 1.0.4 而不是最新的 1.1.0 )。我已经按照步骤操作了,如下图:
var fakePortalUser = new PortalUser()
{
PortalId = new Guid()
};
var fakeQueryablePUser = new List<PortalUser>
{
fakePortalUser
}.AsQueryable().BuildMock();
现在最后一步是使用 GetQueryable()
。我在这里尝试使用:
_portalUserRepositoryMock.GetAll().GetQueryable().Returns(fakeQueryablePUser);
但是我在 GetQueryable()
方法调用下看到了红色波浪线。所以代码无法编译。
你不知道,IQueryable<T>
是由 Entity Framework / Core 处理的实现细节。除非您的业务逻辑实际上创建了 IQueryable<T>
的实现,否则您想要 return 模拟存根对象。
即(请注意,这使用库 Moq
来模拟对象,因为我不确定您使用的是什么,并且实现可能会有所不同。)
_mockedEntityQuery = new Mock<IQueryable<T>>();
_portalUserRepositoryMock = Substitute.For<IPortalUserRepository>();
_portalUserRepositoryMock.GetAll().Returns(_mockedEntityQuery.Object);
如果您 return IQueryable<T>
的一个实例,您还将测试该实现,该实现已由 EF 单元测试完成。单元测试应该只测试单元范围内的代码。
最初的问题与您怀疑的 FirstOrDefaultAsync
一样。该扩展期望可查询对象也有一个 IAsyncQueryProvider
以匹配默认情况下模拟不会出现的异步 EF。
删除 .GetQueryable()
,因为您不需要它。该成员来自其中一个演示如何使用模拟库的示例。
还要确保假数据中的数据与 Where
中的谓词相匹配。
.Where(p => p.UserId == user.Id && p.Portal.PortalType == dto.PortalType)
如果没有要枚举的元素,FirstOrDefault
将 return null。
如果数据不满足过滤器,您将默认返回 null。