forked from ddrilling/AsbCloudServer
improve DbSetMock.
добавлена поддержка асинхронных методов в DbSetMock. AddDbSetMock также мокает свойство соответствующего типа.
This commit is contained in:
parent
9b06438935
commit
0ea49dd72f
@ -2,15 +2,18 @@
|
|||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace AsbCloudWebApi.Tests
|
namespace AsbCloudWebApi.Tests
|
||||||
{
|
{
|
||||||
internal static class TestHelpter
|
internal static class TestHelpter
|
||||||
{
|
{
|
||||||
// Попробовать когда-нибудь https://github.com/MichalJankowskii/Moq.EntityFrameworkCore
|
|
||||||
|
|
||||||
public static IMemoryCache MemoryCache = new MemoryCache(new MemoryCacheOptions());
|
public static IMemoryCache MemoryCache = new MemoryCache(new MemoryCacheOptions());
|
||||||
|
|
||||||
public static AsbCloudDbContext MakeRealTestContext()
|
public static AsbCloudDbContext MakeRealTestContext()
|
||||||
@ -30,22 +33,82 @@ namespace AsbCloudWebApi.Tests
|
|||||||
contextMock.Setup(o => o.Set<T>())
|
contextMock.Setup(o => o.Set<T>())
|
||||||
.Returns(() => dbSetMock.Object);
|
.Returns(() => dbSetMock.Object);
|
||||||
|
|
||||||
|
var dbSetProperty = typeof(IAsbCloudDbContext)
|
||||||
|
.GetProperties()
|
||||||
|
.FirstOrDefault(p => p.PropertyType.IsPublic && p.PropertyType == typeof(DbSet<T>));
|
||||||
|
|
||||||
|
if (dbSetProperty is not null)
|
||||||
|
{
|
||||||
|
// https://learn.microsoft.com/ru-ru/dotnet/api/system.linq.expressions.expression?view=net-7.0
|
||||||
|
var objParameterExpr = Expression.Parameter(typeof(IAsbCloudDbContext), "instance");
|
||||||
|
var propertyExpr = Expression.Property(objParameterExpr, dbSetProperty);
|
||||||
|
var expression = Expression.Lambda<Func<IAsbCloudDbContext, DbSet<T>>>(propertyExpr, objParameterExpr);
|
||||||
|
contextMock.SetupGet(expression).Returns(dbSetMock.Object);
|
||||||
|
}
|
||||||
|
|
||||||
return contextMock;
|
return contextMock;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Mock<DbSet<T>> MakeDbSetMock<T>()
|
public static Mock<DbSet<T>> MakeDbSetMock<T>()
|
||||||
where T : class
|
where T : class
|
||||||
|
=> MakeDbSetMock(new List<T>());
|
||||||
|
|
||||||
|
class DummyAsyncQueriable<T> : IQueryable<T>, IAsyncEnumerable<T>
|
||||||
{
|
{
|
||||||
var dbSetData = new List<T>();
|
private readonly IQueryable<T> queriable;
|
||||||
return MakeDbSetMock(dbSetData);
|
|
||||||
|
public Type ElementType => queriable.ElementType;
|
||||||
|
|
||||||
|
public Expression Expression => queriable.Expression;
|
||||||
|
|
||||||
|
public IQueryProvider Provider => queriable.Provider;
|
||||||
|
|
||||||
|
class QueriableAsyncEminaretor<T2> : IAsyncEnumerator<T2>
|
||||||
|
{
|
||||||
|
private readonly IEnumerator<T2> syncEnumerator;
|
||||||
|
|
||||||
|
public QueriableAsyncEminaretor(IEnumerator<T2> syncEnumerator)
|
||||||
|
{
|
||||||
|
this.syncEnumerator = syncEnumerator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public T2 Current => syncEnumerator.Current;
|
||||||
|
|
||||||
|
public ValueTask DisposeAsync()
|
||||||
|
{
|
||||||
|
syncEnumerator.Dispose();
|
||||||
|
return ValueTask.CompletedTask;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ValueTask<bool> MoveNextAsync()
|
||||||
|
{
|
||||||
|
var result = syncEnumerator.MoveNext();
|
||||||
|
return ValueTask.FromResult(result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public DummyAsyncQueriable(IEnumerable<T> dbSetData)
|
||||||
|
{
|
||||||
|
queriable = dbSetData.ToList().AsQueryable();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var enumerator = this.AsEnumerable().GetEnumerator();
|
||||||
|
return new QueriableAsyncEminaretor<T>(enumerator);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IEnumerator<T> GetEnumerator()
|
||||||
|
=> queriable.GetEnumerator();
|
||||||
|
|
||||||
|
IEnumerator IEnumerable.GetEnumerator()
|
||||||
|
=> queriable.GetEnumerator();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Mock<DbSet<T>> MakeDbSetMock<T>(IEnumerable<T> dbSetData)
|
public static Mock<DbSet<T>> MakeDbSetMock<T>(IEnumerable<T> dbSetData)
|
||||||
where T : class
|
where T : class
|
||||||
{
|
{
|
||||||
var dbSetDataQueriable = dbSetData
|
var dbSetDataQueriable = new DummyAsyncQueriable<T>(dbSetData);
|
||||||
.ToList()
|
|
||||||
.AsQueryable();
|
|
||||||
|
|
||||||
Mock<DbSet<T>> dbSetMock = new();
|
Mock<DbSet<T>> dbSetMock = new();
|
||||||
dbSetMock.As<IQueryable<T>>().Setup(o => o.Provider).Returns(() => dbSetDataQueriable.Provider);
|
dbSetMock.As<IQueryable<T>>().Setup(o => o.Provider).Returns(() => dbSetDataQueriable.Provider);
|
||||||
@ -53,6 +116,10 @@ namespace AsbCloudWebApi.Tests
|
|||||||
dbSetMock.As<IQueryable<T>>().Setup(o => o.ElementType).Returns(() => dbSetDataQueriable.ElementType);
|
dbSetMock.As<IQueryable<T>>().Setup(o => o.ElementType).Returns(() => dbSetDataQueriable.ElementType);
|
||||||
dbSetMock.As<IQueryable<T>>().Setup(o => o.GetEnumerator()).Returns(() => dbSetDataQueriable.GetEnumerator());
|
dbSetMock.As<IQueryable<T>>().Setup(o => o.GetEnumerator()).Returns(() => dbSetDataQueriable.GetEnumerator());
|
||||||
|
|
||||||
|
dbSetMock.As<IAsyncEnumerable<T>>()
|
||||||
|
.Setup(o => o.GetAsyncEnumerator(It.IsAny<CancellationToken>()))
|
||||||
|
.Returns(() => dbSetDataQueriable.GetAsyncEnumerator());
|
||||||
|
|
||||||
return dbSetMock;
|
return dbSetMock;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user