using AsbCloudDb.Model; using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Caching.Memory; using Moq; using System; using System.Collections; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Threading; using System.Threading.Tasks; namespace AsbCloudWebApi.Tests { internal static class TestHelpter { public static IMemoryCache MemoryCache = new MemoryCache(new MemoryCacheOptions()); public static AsbCloudDbContext MakeRealTestContext() { var options = new DbContextOptionsBuilder() .UseNpgsql("Host=localhost;Database=tests;Username=postgres;Password=q;Persist Security Info=True;Include Error Detail=True") .Options; var context = new AsbCloudDbContext(options); context.Database.EnsureCreated(); return context; } public static Mock AddDbSetMock(this Mock contextMock, IEnumerable dbSetData) where T : class { var dbSetMock = MakeDbSetMock(dbSetData); contextMock.Setup(o => o.Set()) .Returns(() => dbSetMock.Object); var dbSetProperty = typeof(IAsbCloudDbContext) .GetProperties() .FirstOrDefault(p => p.PropertyType.IsPublic && p.PropertyType == typeof(DbSet)); 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>>(propertyExpr, objParameterExpr); contextMock.SetupGet(expression).Returns(dbSetMock.Object); } return contextMock; } public static Mock> MakeDbSetMock() where T : class => MakeDbSetMock(new List()); class DummyAsyncQueriable : IQueryable, IAsyncEnumerable { private readonly IQueryable queriable; public Type ElementType => queriable.ElementType; public Expression Expression => queriable.Expression; public IQueryProvider Provider => queriable.Provider; class QueriableAsyncEminaretor : IAsyncEnumerator { private readonly IEnumerator syncEnumerator; public QueriableAsyncEminaretor(IEnumerator syncEnumerator) { this.syncEnumerator = syncEnumerator; } public T2 Current => syncEnumerator.Current; public ValueTask DisposeAsync() { syncEnumerator.Dispose(); return ValueTask.CompletedTask; } public ValueTask MoveNextAsync() { var result = syncEnumerator.MoveNext(); return ValueTask.FromResult(result); } } public DummyAsyncQueriable(IEnumerable dbSetData) { queriable = dbSetData.ToList().AsQueryable(); } public IAsyncEnumerator GetAsyncEnumerator(CancellationToken cancellationToken = default) { var enumerator = this.AsEnumerable().GetEnumerator(); return new QueriableAsyncEminaretor(enumerator); } public IEnumerator GetEnumerator() => queriable.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => queriable.GetEnumerator(); } public static Mock> MakeDbSetMock(IEnumerable dbSetData) where T : class { var dbSetDataQueriable = new DummyAsyncQueriable(dbSetData); Mock> dbSetMock = new(); dbSetMock.As>().Setup(o => o.Provider).Returns(() => dbSetDataQueriable.Provider); dbSetMock.As>().Setup(o => o.Expression).Returns(() => dbSetDataQueriable.Expression); dbSetMock.As>().Setup(o => o.ElementType).Returns(() => dbSetDataQueriable.ElementType); dbSetMock.As>().Setup(o => o.GetEnumerator()).Returns(() => dbSetDataQueriable.GetEnumerator()); dbSetMock.As>() .Setup(o => o.GetAsyncEnumerator(It.IsAny())) .Returns(() => dbSetDataQueriable.GetAsyncEnumerator()); return dbSetMock; } } }