如何从模拟对象返回IQueryable <TEntity>对象?

时间:2019-09-05 14:28:50

标签: c# asynchronous .net-core entity-framework-core nsubstitute

我试图告诉模拟对象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()方法调用下看到了红色的弯曲线。因此代码将无法编译。

2 个答案:

答案 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单元测试完成。单元测试应仅测试单元范围内的代码。