Sto provando a scrivere il test unitario prendendo in giro. Il mio test sta GetAll
giro il metodo GetAll
che utilizza il metodo FirstOrDefaultAsync
. Se cambio FirstOrDefaultAsync
su FirstOrDefault
mio test funziona bene ma continua a fallire quando FirstOrDefaultAsync
.
Il mio codice di prova dell'unità è sotto
[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");
}
Codice che sto cercando di testare
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());
}
Il mio metodo di estensione
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;
}
Eccezione che sto ricevendo
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
Risultato StackTrace:
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.
Per IDbAsyncQueryProvider
query asincrone è necessario implementare IDbAsyncQueryProvider
interfaccia IDbAsyncQueryProvider
. Non so come si implementa il metodo GenerateMockDbSetForAsync
ma qui è completo su metodi asinconici di simulazione.