2016-10-15 68 views
0

我想通过嘲笑编写单元测试。我的测试是嘲笑使用FirstOrDefaultAsync方法的GetAll方法。如果我将FirstOrDefaultAsync更改为FirstOrDefault我的测试正常,但当我放回FirstOrDefaultAsync时仍然失败。使用NSubstitute,实体框架嘲弄FirstOrDefualtAscync方法抛出异常

我的单元测试代码如下

[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("[email protected].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; 
    } 

异常我越来越

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 

结果堆栈跟踪:

at System.Data.Entity.QueryableExtensions.FirstOrDefaultAsyncTSource 
at System.Data.Entity.QueryableExtensions.FirstOrDefaultAsyncTSource 
at PostAnything.Business.Implementation.UsersService.d__2.MoveNext() in C:\TFS\PostAnything\PostAnything.Business\Implementation\UsersService.cs:line 28 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult() 
at PostAnything.Business.Tests.UsersServiceTests.d__5.MoveNext() in C:\TFS\PostAnything\PostAnything.Business.Tests\UsersServiceTests.cs:line 49 
--- End of stack trace from previous location where exception was thrown --- 
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) 
at System.Runtime.CompilerServices.TaskAwaiter.GetResult() 
Result Message: 
Test method PostAnything.Business.Tests.UsersServiceTests.GetAsync_WithUser_ReturnsOk threw exception: 
System.InvalidOperationException: The provider for the source IQueryable doesn't implement IDbAsyncQueryProvider. Only providers that implement IDbAsyncQueryProvider can be used for Entity Framework asynchronous operations. For more details see http://go.microsoft.com/fwlink/?LinkId=287068. 

回答

0

为了嘲笑你需要实现IDbAsyncQueryProvider界面异步查询。我不知道你是如何实现GenerateMockDbSetForAsync方法,但这里是完全嘲笑异步方法。

Testing with a mocking framework (EF6 onwards)

Testing with your own test doubles (EF6 onwards)

+0

我已经尝试过这一点,但得到了同样的错误,但我已经更新了我的扩展方法问题 –

+0

查询更改为'Uow.User.GetAll()。其中​​(x = > x.EmailAddress == email)'并检查它是否有效。 –

+0

如果您要在我的代码中更改该查询,我试图测试它, –

相关问题