我试图告诉模拟对象GetAll()
上的方法_portalUserRepositoryMock
返回类型IQueryable<TEntity>
的对象。我知道它是这种类型的,因为要测试的类中的方法会返回这种类型。
我无法提出解决方案。 我看到了这个post,但是在尝试将library包含到我的项目中时遇到了错误。有关Microsoft.EntityFrameworkCore版本的信息-导致了更多问题。
我为得到此错误所做的是:
_portalUserRepositoryMock = Substitute.For<IPortalUserRepository>();
_portalUserRepositoryMock.GetAll().Returns(fakeQueryablePUser.AsQueryable());
被测类使用这样的存储库:
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;
}
}
我收到此错误:
消息:System.InvalidOperationException:源的提供程序 IQueryable没有实现IAsyncQueryProvider。仅提供者 实现IEntityQueryProvider可用于实体框架 异步操作。
我认为由于正在使用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()
方法调用下看到了红色的弯曲线。因此代码将无法编译。
答案 0 :(得分:2)
最初的问题是您怀疑与FirstOrDefaultAsync
有关。该扩展名期望可查询对象也具有IAsyncQueryProvider
,以匹配默认情况下不会被模拟的异步EF。
删除.GetQueryable()
,因为您不需要它。该成员来自其中一个示例,以演示如何使用模拟库。
还要确保假数据中包含与Where
中的谓词匹配的数据。
.Where(p => p.UserId == user.Id && p.Portal.PortalType == dto.PortalType)
如果没有要枚举的元素, FirstOrDefault
将返回 null 。
如果数据不满足过滤条件,则默认情况下将返回 null 。
答案 1 :(得分:0)
您没有,IQueryable<T>
是由Entity Framework / Core处理的实现细节。除非您的业务逻辑实际上创建了IQueryable<T>
的实现,否则您想返回一个模拟存根对象。
即(请注意,它使用库Moq
来模拟对象,因为我不确定您使用的是什么,并且实现可能会有所不同。)
_mockedEntityQuery = new Mock<IQueryable<T>>();
_portalUserRepositoryMock = Substitute.For<IPortalUserRepository>();
_portalUserRepositoryMock.GetAll().Returns(_mockedEntityQuery.Object);
如果返回IQueryable<T>
的实例,那么您还将测试该实现,而该实现已由EF单元测试完成。单元测试应仅测试单元范围内的代码。