Skip to content

Commit 8ace215

Browse files
committed
test: 🧪 refactor identity integration tests
1 parent d4ccb94 commit 8ace215

File tree

48 files changed

+479
-308
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+479
-308
lines changed

.editorconfig

+4
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,8 @@ resharper_web_config_module_not_resolved_highlighting = warning
248248
resharper_web_config_type_not_resolved_highlighting = warning
249249
resharper_web_config_wrong_module_highlighting = warning
250250

251+
# https://www.jetbrains.com/help/rider/ClassNeverInstantiated.Global.html
252+
resharper_class_never_instantiated_global_highlighting = none
251253

252254
##################################################################################
253255
## https://github.com/DotNetAnalyzers/StyleCopAnalyzers/tree/master/documentation
@@ -375,6 +377,8 @@ dotnet_diagnostic.sa1101.severity = None
375377
# The keywords within the declaration of an element do not follow a standard ordering scheme.
376378
dotnet_diagnostic.SA1206.severity = None
377379

380+
dotnet_diagnostic.SA1404.severity = None
381+
378382
##################################################################################
379383
## https://github.com/meziantou/Meziantou.Analyzer/tree/main/docs
380384
## Meziantou.Analyzer

.husky/pre-commit

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@
33

44
# dotnet format --verbosity diagnostic
55
dotnet csharpier . && git add -A .
6+
dotnet csharpier --check .

src/ApiGateway/FoodDelivery.ApiGateway/FoodDelivery.ApiGateway.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<ItemGroup>
2727
<PackageReference Include="Duende.BFF.Yarp" />
2828
<PackageReference Include="Serilog.AspNetCore" />
29-
<PackageReference Include="Serilog.Sinks.SpectreConsole" />
29+
<PackageReference Include="Serilog.Sinks.Spectre" />
3030
<PackageReference Include="Yarp.ReverseProxy" />
3131
</ItemGroup>
3232

src/ApiGateway/FoodDelivery.ApiGateway/Program.cs

+2-7
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,16 @@
11
using System.IdentityModel.Tokens.Jwt;
2-
using BuildingBlocks.Core.Messaging;
32
using BuildingBlocks.Logging;
43
using MassTransit;
5-
using Microsoft.IdentityModel.Logging;
64
using Serilog;
75
using Serilog.Events;
8-
using Serilog.Sinks.SpectreConsole;
6+
using Serilog.Sinks.Spectre;
97
using Yarp.ReverseProxy.Transforms;
108
using MessageHeaders = BuildingBlocks.Core.Messaging.MessageHeaders;
119

1210
Log.Logger = new LoggerConfiguration()
1311
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
1412
.Enrich.FromLogContext()
15-
.WriteTo.SpectreConsole(
16-
"{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}",
17-
LogEventLevel.Information
18-
)
13+
.WriteTo.Spectre("{Timestamp:HH:mm:ss} [{Level:u4}] {Message:lj}{NewLine}{Exception}", LogEventLevel.Information)
1914
.CreateLogger();
2015

2116
var builder = WebApplication.CreateBuilder(args);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
namespace BuildingBlocks.Abstractions.Persistence;
2+
3+
public interface ITestDataSeeder
4+
{
5+
int Order { get; }
6+
Task SeedAllAsync();
7+
}

src/BuildingBlocks/BuildingBlocks.Core/Extensions/QueryableExtensions.cs

+24-9
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using AutoMapper.QueryableExtensions;
44
using BuildingBlocks.Abstractions.Core.Paging;
55
using BuildingBlocks.Core.Paging;
6+
using Microsoft.EntityFrameworkCore;
67
using Sieve.Models;
78
using Sieve.Services;
89

@@ -29,10 +30,13 @@ CancellationToken cancellationToken
2930

3031
// https://github.com/Biarity/Sieve/issues/34#issuecomment-403817573
3132
var result = sieveProcessor.Apply(sieveModel, queryable, applyPagination: false);
33+
#pragma warning disable AsyncFixer02
34+
// The provider for the source 'IQueryable' doesn't implement 'IAsyncQueryProvider'. Only providers that implement 'IAsyncQueryProvider' can be used for Entity Framework asynchronous operations.
3235
var total = result.Count();
36+
#pragma warning restore AsyncFixer02
3337
result = sieveProcessor.Apply(sieveModel, queryable, applyFiltering: false, applySorting: false);
3438

35-
var items = await result.ToAsyncEnumerable().ToListAsync(cancellationToken: cancellationToken);
39+
var items = await result.AsNoTracking().ToAsyncEnumerable().ToListAsync(cancellationToken: cancellationToken);
3640

3741
return PageList<TEntity>.Create(items.AsReadOnly(), pageRequest.PageNumber, pageRequest.PageSize, total);
3842
}
@@ -57,12 +61,18 @@ CancellationToken cancellationToken
5761

5862
// https://github.com/Biarity/Sieve/issues/34#issuecomment-403817573
5963
var result = sieveProcessor.Apply(sieveModel, queryable, applyPagination: false);
64+
#pragma warning disable AsyncFixer02
65+
// The provider for the source 'IQueryable' doesn't implement 'IAsyncQueryProvider'. Only providers that implement 'IAsyncQueryProvider' can be used for Entity Framework asynchronous operations.
6066
var total = result.Count();
67+
#pragma warning restore AsyncFixer02
6168
result = sieveProcessor.Apply(sieveModel, queryable, applyFiltering: false, applySorting: false); // Only applies pagination
6269

6370
var projectedQuery = result.ProjectTo<TResult>(configurationProvider);
6471

65-
var items = await projectedQuery.ToAsyncEnumerable().ToListAsync(cancellationToken: cancellationToken);
72+
var items = await projectedQuery
73+
.AsNoTracking()
74+
.ToAsyncEnumerable()
75+
.ToListAsync(cancellationToken: cancellationToken);
6676

6777
return PageList<TResult>.Create(items.AsReadOnly(), pageRequest.PageNumber, pageRequest.PageSize, total);
6878
}
@@ -87,12 +97,18 @@ CancellationToken cancellationToken
8797

8898
// https://github.com/Biarity/Sieve/issues/34#issuecomment-403817573
8999
var result = sieveProcessor.Apply(sieveModel, queryable, applyPagination: false);
100+
#pragma warning disable AsyncFixer02
101+
// The provider for the source 'IQueryable' doesn't implement 'IAsyncQueryProvider'. Only providers that implement 'IAsyncQueryProvider' can be used for Entity Framework asynchronous operations.
90102
var total = result.Count();
103+
#pragma warning restore AsyncFixer02
91104
result = sieveProcessor.Apply(sieveModel, queryable, applyFiltering: false, applySorting: false); // Only applies pagination
92105

93106
var projectedQuery = projectionFunc(result);
94107

95-
var items = await projectedQuery.ToAsyncEnumerable().ToListAsync(cancellationToken: cancellationToken);
108+
var items = await projectedQuery
109+
.AsNoTracking()
110+
.ToAsyncEnumerable()
111+
.ToListAsync(cancellationToken: cancellationToken);
96112

97113
return PageList<TResult>.Create(items.AsReadOnly(), pageRequest.PageNumber, pageRequest.PageSize, total);
98114
}
@@ -120,12 +136,7 @@ public static async Task<IPageList<TResult>> ApplyPagingAsync<TEntity, TResult,
120136
query = query.OrderByDescending(sortExpression);
121137
}
122138

123-
return await query.ApplyPagingAsync<TEntity, TResult>(
124-
pageRequest,
125-
sieveProcessor,
126-
projectionFunc,
127-
cancellationToken
128-
);
139+
return await query.ApplyPagingAsync(pageRequest, sieveProcessor, projectionFunc, cancellationToken);
129140
}
130141

131142
public static async Task<IPageList<TResult>> ApplyPagingAsync<TEntity, TResult>(
@@ -148,11 +159,15 @@ CancellationToken cancellationToken
148159

149160
// https://github.com/Biarity/Sieve/issues/34#issuecomment-403817573
150161
var result = sieveProcessor.Apply(sieveModel, queryable, applyPagination: false);
162+
#pragma warning disable AsyncFixer02
163+
// The provider for the source 'IQueryable' doesn't implement 'IAsyncQueryProvider'. Only providers that implement 'IAsyncQueryProvider' can be used for Entity Framework asynchronous operations.
151164
var total = result.Count();
165+
#pragma warning restore AsyncFixer02
152166
result = sieveProcessor.Apply(sieveModel, queryable, applyFiltering: false, applySorting: false); // Only applies pagination
153167

154168
var items = await result
155169
.Select(x => map(x))
170+
.AsNoTracking()
156171
.ToAsyncEnumerable()
157172
.ToListAsync(cancellationToken: cancellationToken);
158173

src/BuildingBlocks/BuildingBlocks.Core/Messaging/MessagingConstants.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,5 @@ namespace BuildingBlocks.Core.Messaging;
22

33
public static class MessagingConstants
44
{
5-
public const string PrimaryExchangePostfix = "_primary_exchange";
5+
public const string PrimaryExchangePostfix = ".primary_exchange";
66
}

src/BuildingBlocks/BuildingBlocks.Core/Persistence/Extensions/DependencyInjectionExtensions.cs

+16-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
namespace BuildingBlocks.Core.Persistence.Extensions;
55

6-
internal static class DependencyInjectionExtensions
6+
public static class DependencyInjectionExtensions
77
{
88
internal static IServiceCollection AddPersistenceCore(
99
this IServiceCollection services,
@@ -12,9 +12,24 @@ params Assembly[] assembliesToScan
1212
{
1313
services.ScanAndRegisterDbExecutors(assembliesToScan);
1414

15+
services.RegisterDataSeeders(assembliesToScan);
16+
1517
services.AddHostedService<SeedWorker>();
1618
services.AddScoped<IMigrationManager, MigrationManager>();
1719

1820
return services;
1921
}
22+
23+
public static void RegisterDataSeeders(this IServiceCollection services, Assembly[] assembliesToScan)
24+
{
25+
services.Scan(scan =>
26+
scan.FromAssemblies(assembliesToScan)
27+
.AddClasses(classes => classes.AssignableTo<IDataSeeder>())
28+
.AsImplementedInterfaces()
29+
.WithScopedLifetime()
30+
.AddClasses(classes => classes.AssignableTo<ITestDataSeeder>())
31+
.AsImplementedInterfaces()
32+
.WithScopedLifetime()
33+
);
34+
}
2035
}

src/BuildingBlocks/BuildingBlocks.Core/Persistence/SeedWorker.cs

+19-11
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using BuildingBlocks.Abstractions.Persistence;
2+
using BuildingBlocks.Core.Web.Extensions;
23
using Microsoft.AspNetCore.Hosting;
34
using Microsoft.Extensions.Hosting;
45
using Microsoft.Extensions.Logging;
@@ -15,15 +16,25 @@ IWebHostEnvironment webHostEnvironment
1516
{
1617
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
1718
{
18-
if (!webHostEnvironment.IsEnvironment("test"))
19-
{
20-
logger.LogInformation("Seed worker started");
19+
logger.LogInformation("Seed worker started");
2120

22-
// https://stackoverflow.com/questions/38238043/how-and-where-to-call-database-ensurecreated-and-database-migrate
23-
// https://www.michalbialecki.com/2020/07/20/adding-entity-framework-core-5-migrations-to-net-5-project/
24-
using var serviceScope = serviceScopeFactory.CreateScope();
25-
var seeders = serviceScope.ServiceProvider.GetServices<IDataSeeder>();
21+
using var serviceScope = serviceScopeFactory.CreateScope();
2622

23+
// https://stackoverflow.com/questions/38238043/how-and-where-to-call-database-ensurecreated-and-database-migrate
24+
// https://www.michalbialecki.com/2020/07/20/adding-entity-framework-core-5-migrations-to-net-5-project/
25+
var testSeeders = serviceScope.ServiceProvider.GetServices<ITestDataSeeder>();
26+
var seeders = serviceScope.ServiceProvider.GetServices<IDataSeeder>();
27+
if (webHostEnvironment.IsTest())
28+
{
29+
foreach (var testDataSeeder in testSeeders.OrderBy(x => x.Order))
30+
{
31+
logger.LogInformation("Seeding '{Seed}' started...", testDataSeeder.GetType().Name);
32+
await testDataSeeder.SeedAllAsync();
33+
logger.LogInformation("Seeding '{Seed}' ended...", testDataSeeder.GetType().Name);
34+
}
35+
}
36+
else
37+
{
2738
foreach (var seeder in seeders.OrderBy(x => x.Order))
2839
{
2940
logger.LogInformation("Seeding '{Seed}' started...", seeder.GetType().Name);
@@ -35,10 +46,7 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
3546

3647
public override Task StopAsync(CancellationToken cancellationToken)
3748
{
38-
if (!webHostEnvironment.IsEnvironment("test"))
39-
{
40-
logger.LogInformation("Seed worker stopped");
41-
}
49+
logger.LogInformation("Seed worker stopped");
4250

4351
return base.StopAsync(cancellationToken);
4452
}

src/BuildingBlocks/BuildingBlocks.Integration.MassTransit/CustomEntityNameFormatter.cs

+20
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,23 @@ public string FormatEntityName<T>()
2727
return $"{typeof(T).Name.Underscore()}{MessagingConstants.PrimaryExchangePostfix}";
2828
}
2929
}
30+
31+
public class CustomEntityNameFormatter<TMessage> : IMessageEntityNameFormatter<TMessage>
32+
where TMessage : class
33+
{
34+
public string FormatEntityName()
35+
{
36+
// Check if T implements IEventEnvelope
37+
if (typeof(IEventEnvelope).IsAssignableFrom(typeof(TMessage)))
38+
{
39+
var messageProperty = typeof(TMessage).GetProperty(nameof(IEventEnvelope.Message));
40+
if (typeof(IMessage).IsAssignableFrom(messageProperty!.PropertyType))
41+
{
42+
return $"{messageProperty.PropertyType.Name.Underscore()}{MessagingConstants.PrimaryExchangePostfix}";
43+
}
44+
}
45+
46+
// Return a default value if T does not implement IEventEnvelop or Message property is not found
47+
return $"{typeof(TMessage).Name.Underscore()}{MessagingConstants.PrimaryExchangePostfix}";
48+
}
49+
}

0 commit comments

Comments
 (0)