使用NSubstitute进行模拟,实体框架FirstOrDefualtAscync方法抛出异常

时间:2016-10-15 03:35:31

标签: c# entity-framework entity-framework-6 nsubstitute

我试图通过嘲笑来编写单元测试。我的测试是模拟使用 $.ajax({ context: /* element or object which should be `this` at `success` */ }) 方法的GetAll方法。如果我将FirstOrDefaultAsync更改为FirstOrDefaultAsync,我的测试工作正常,但当我放回FirstOrDefault时,它仍会失败。

我的单元测试代码在

之下
FirstOrDefaultAsync

我正在尝试测试代码

[TestMethod]
public async Task GetAsync_WithUser_ReturnsOk()
{
    var data = GetUserResult();

    var mockContext = Substitute.For<IPostAnythingContext>();
    var mockSet = data.GenerateMockDbSetForAsync();
    mockContext.Users.Returns(mockSet);

    uow.User.GetAll().Returns(data);
    var result = await sut.GetAsync("a@a.com");
}

我的扩展方法

public async Task<Result<Users>> GetAsync(string email)
{
    var result = Uow.User.GetAll()
                .Where(x => x.EmailAddress == email)
                .Include(x => x.UsersUsersTypes);
    return Result.Ok(await result.FirstOrDefaultAsync());
}

我得到的例外

public static DbSet<TEntity> GenerateMockDbSetForAsync<TEntity>(this IEnumerable<TEntity> queryableEnumerable) where TEntity : class
    {
       var queryable = queryableEnumerable as IQueryable<TEntity> ??      queryableEnumerable.AsQueryable();

       var mockSet = Substitute.For<DbSet<TEntity>, IQueryable<TEntity>, IDbAsyncEnumerable<TEntity>>();

                    // async support
     var castMockSet = (IQueryable<TEntity>)mockSet;
     var castAsyncEnum = (IDbAsyncEnumerable<TEntity>)mockSet;
         castAsyncEnum.GetAsyncEnumerator().Returns(new TestDbAsyncEnumerator<TEntity>(queryable.GetEnumerator()));
         castMockSet.Provider.Returns(new TestDbAsyncQueryProvider<TEntity>(queryable.Provider));

       castMockSet.Expression.Returns(queryable.Expression);
       castMockSet.ElementType.Returns(queryable.ElementType);
       castMockSet.GetEnumerator().Returns(queryable.GetEnumerator());
       return mockSet;
    }

结果StackTrace:

Test Name: GetAsync_WithUser_ReturnsOk
Test FullName: PostAnything.Business.Tests.UsersServiceTests.GetAsync_WithUser_ReturnsOk
Test Source: C:\TFS\PostAnything\PostAnything.Business.Tests\UsersServiceTests.cs : line 40
Test Outcome: Failed
Test Duration: 0:00:02.5118084

1 个答案:

答案 0 :(得分:0)

为了模拟异步查询,您需要实现IDbAsyncQueryProvider接口。我不知道你是如何实现GenerateMockDbSetForAsync方法的,但这里完全是在模拟异步方法上完成的。

Testing with a mocking framework (EF6 onwards)

Testing with your own test doubles (EF6 onwards)