mirror of
https://github.com/alex289/CleanArchitecture.git
synced 2025-08-22 19:28:34 +00:00
feat: Use TestContainers for integration tests
This commit is contained in:
parent
35d7482ade
commit
2c7748d877
@ -10,10 +10,13 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.4" />
|
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.4" />
|
||||||
<PackageReference Include="Microsoft.Data.Sqlite.Core" Version="8.0.4" />
|
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.4" />
|
<PackageReference Include="Microsoft.EntityFrameworkCore.Proxies" Version="8.0.4" />
|
||||||
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="8.0.4" />
|
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
|
||||||
|
<PackageReference Include="Respawn" Version="6.2.1" />
|
||||||
|
<PackageReference Include="Testcontainers" Version="3.8.0" />
|
||||||
|
<PackageReference Include="Testcontainers.MsSql" Version="3.8.0" />
|
||||||
|
<PackageReference Include="Testcontainers.RabbitMq" Version="3.8.0" />
|
||||||
|
<PackageReference Include="Testcontainers.Redis" Version="3.8.0" />
|
||||||
<PackageReference Include="xunit" Version="2.7.0" />
|
<PackageReference Include="xunit" Version="2.7.0" />
|
||||||
<PackageReference Include="Xunit.Priority" Version="1.1.6" />
|
<PackageReference Include="Xunit.Priority" Version="1.1.6" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.7">
|
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.7">
|
||||||
|
@ -1,46 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Data.Common;
|
|
||||||
using System.Linq;
|
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.EntityFrameworkCore.Diagnostics;
|
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
|
|
||||||
namespace CleanArchitecture.IntegrationTests.Extensions;
|
|
||||||
|
|
||||||
public static class FunctionalTestsServiceCollectionExtensions
|
|
||||||
{
|
|
||||||
public static IServiceCollection SetupTestDatabase<TContext>(this IServiceCollection services,
|
|
||||||
DbConnection connection) where TContext : DbContext
|
|
||||||
{
|
|
||||||
var descriptor = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<TContext>));
|
|
||||||
if (descriptor is not null)
|
|
||||||
services.Remove(descriptor);
|
|
||||||
|
|
||||||
services.AddScoped(p =>
|
|
||||||
DbContextOptionsFactory<TContext>(
|
|
||||||
p,
|
|
||||||
(_, options) => options
|
|
||||||
.ConfigureWarnings(b => b.Log(CoreEventId.ManyServiceProvidersCreatedWarning))
|
|
||||||
.UseLazyLoadingProxies()
|
|
||||||
.UseSqlite(connection)));
|
|
||||||
|
|
||||||
return services;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static DbContextOptions<TContext> DbContextOptionsFactory<TContext>(
|
|
||||||
IServiceProvider applicationServiceProvider,
|
|
||||||
Action<IServiceProvider, DbContextOptionsBuilder> optionsAction)
|
|
||||||
where TContext : DbContext
|
|
||||||
{
|
|
||||||
var builder = new DbContextOptionsBuilder<TContext>(
|
|
||||||
new DbContextOptions<TContext>(new Dictionary<Type, IDbContextOptionsExtension>()));
|
|
||||||
|
|
||||||
builder.UseApplicationServiceProvider(applicationServiceProvider);
|
|
||||||
|
|
||||||
optionsAction.Invoke(applicationServiceProvider, builder);
|
|
||||||
|
|
||||||
return builder.Options;
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,23 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using CleanArchitecture.IntegrationTests.Infrastructure;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace CleanArchitecture.IntegrationTests.Fixtures;
|
||||||
|
|
||||||
|
public sealed class DatabaseFixture : IAsyncLifetime
|
||||||
|
{
|
||||||
|
public static string TestRunDbName { get; } = $"CleanArchitecture-Integration-{Guid.NewGuid()}";
|
||||||
|
|
||||||
|
public async Task DisposeAsync()
|
||||||
|
{
|
||||||
|
var db = DatabaseAccessor.GetOrCreateAsync(TestRunDbName);
|
||||||
|
await db.DisposeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
var db = DatabaseAccessor.GetOrCreateAsync(TestRunDbName);
|
||||||
|
await db.InitializeAsync();
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using CleanArchitecture.Domain.Constants;
|
using CleanArchitecture.Domain.Constants;
|
||||||
using CleanArchitecture.Domain.Entities;
|
using CleanArchitecture.Domain.Entities;
|
||||||
using CleanArchitecture.Domain.Enums;
|
using CleanArchitecture.Domain.Enums;
|
||||||
@ -8,20 +9,21 @@ using CleanArchitecture.IntegrationTests.Infrastructure;
|
|||||||
using CleanArchitecture.IntegrationTests.Infrastructure.Auth;
|
using CleanArchitecture.IntegrationTests.Infrastructure.Auth;
|
||||||
using Microsoft.AspNetCore.Mvc.Testing;
|
using Microsoft.AspNetCore.Mvc.Testing;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
namespace CleanArchitecture.IntegrationTests.Fixtures;
|
namespace CleanArchitecture.IntegrationTests.Fixtures;
|
||||||
|
|
||||||
public class TestFixtureBase
|
public class TestFixtureBase : IAsyncLifetime
|
||||||
{
|
{
|
||||||
public HttpClient ServerClient { get; }
|
public HttpClient ServerClient { get; }
|
||||||
protected WebApplicationFactory<Program> Factory { get; }
|
protected CleanArchitectureWebApplicationFactory Factory { get; }
|
||||||
|
|
||||||
public TestFixtureBase(bool useTestAuthentication = true)
|
public TestFixtureBase(bool useTestAuthentication = true)
|
||||||
{
|
{
|
||||||
Factory = new CleanArchitectureWebApplicationFactory(
|
Factory = new CleanArchitectureWebApplicationFactory(
|
||||||
SeedTestData,
|
|
||||||
RegisterCustomServicesHandler,
|
RegisterCustomServicesHandler,
|
||||||
useTestAuthentication);
|
useTestAuthentication,
|
||||||
|
DatabaseFixture.TestRunDbName);
|
||||||
|
|
||||||
ServerClient = Factory.CreateClient();
|
ServerClient = Factory.CreateClient();
|
||||||
ServerClient.Timeout = TimeSpan.FromMinutes(5);
|
ServerClient.Timeout = TimeSpan.FromMinutes(5);
|
||||||
@ -29,17 +31,17 @@ public class TestFixtureBase
|
|||||||
|
|
||||||
protected virtual void SeedTestData(ApplicationDbContext context)
|
protected virtual void SeedTestData(ApplicationDbContext context)
|
||||||
{
|
{
|
||||||
context.Users.Add(new User(
|
}
|
||||||
TestAuthenticationOptions.TestUserId,
|
|
||||||
Ids.Seed.TenantId,
|
|
||||||
TestAuthenticationOptions.Email,
|
|
||||||
TestAuthenticationOptions.FirstName,
|
|
||||||
TestAuthenticationOptions.LastName,
|
|
||||||
// !Password123#
|
|
||||||
"$2a$12$Blal/uiFIJdYsCLTMUik/egLbfg3XhbnxBC6Sb5IKz2ZYhiU/MzL2",
|
|
||||||
UserRole.Admin));
|
|
||||||
|
|
||||||
context.SaveChanges();
|
private async Task PrepareDatabaseAsync()
|
||||||
|
{
|
||||||
|
await Factory.RespawnDatabaseAsync();
|
||||||
|
|
||||||
|
using var scope = Factory.Services.CreateScope();
|
||||||
|
await using var dbContext = scope.ServiceProvider.GetRequiredService<ApplicationDbContext>();
|
||||||
|
|
||||||
|
SeedTestData(dbContext);
|
||||||
|
await dbContext.SaveChangesAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void RegisterCustomServicesHandler(
|
protected virtual void RegisterCustomServicesHandler(
|
||||||
@ -48,4 +50,14 @@ public class TestFixtureBase
|
|||||||
IServiceProvider scopedServices)
|
IServiceProvider scopedServices)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
await PrepareDatabaseAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task DisposeAsync()
|
||||||
|
{
|
||||||
|
return Task.CompletedTask;
|
||||||
|
}
|
||||||
}
|
}
|
@ -1,13 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using CleanArchitecture.Infrastructure.Database;
|
using CleanArchitecture.Infrastructure.Database;
|
||||||
using CleanArchitecture.Infrastructure.Extensions;
|
|
||||||
using CleanArchitecture.IntegrationTests.Extensions;
|
|
||||||
using CleanArchitecture.IntegrationTests.Infrastructure.Auth;
|
using CleanArchitecture.IntegrationTests.Infrastructure.Auth;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Mvc.Testing;
|
using Microsoft.AspNetCore.Mvc.Testing;
|
||||||
using Microsoft.Data.Sqlite;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
|
||||||
using Microsoft.EntityFrameworkCore.Storage;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace CleanArchitecture.IntegrationTests.Infrastructure;
|
namespace CleanArchitecture.IntegrationTests.Infrastructure;
|
||||||
@ -21,20 +19,19 @@ public sealed class CleanArchitectureWebApplicationFactory : WebApplicationFacto
|
|||||||
ServiceProvider serviceProvider,
|
ServiceProvider serviceProvider,
|
||||||
IServiceProvider scopedServices);
|
IServiceProvider scopedServices);
|
||||||
|
|
||||||
private readonly AddCustomSeedDataHandler? _addCustomSeedDataHandler;
|
private readonly string _instanceDatabaseName;
|
||||||
private readonly bool _addTestAuthentication;
|
|
||||||
|
|
||||||
private readonly SqliteConnection _connection = new("DataSource=:memory:");
|
private readonly bool _addTestAuthentication;
|
||||||
private readonly RegisterCustomServicesHandler? _registerCustomServicesHandler;
|
private readonly RegisterCustomServicesHandler? _registerCustomServicesHandler;
|
||||||
|
|
||||||
public CleanArchitectureWebApplicationFactory(
|
public CleanArchitectureWebApplicationFactory(
|
||||||
AddCustomSeedDataHandler? addCustomSeedDataHandler,
|
|
||||||
RegisterCustomServicesHandler? registerCustomServicesHandler,
|
RegisterCustomServicesHandler? registerCustomServicesHandler,
|
||||||
bool addTestAuthentication)
|
bool addTestAuthentication,
|
||||||
|
string instanceDatabaseName)
|
||||||
{
|
{
|
||||||
_addCustomSeedDataHandler = addCustomSeedDataHandler;
|
|
||||||
_registerCustomServicesHandler = registerCustomServicesHandler;
|
_registerCustomServicesHandler = registerCustomServicesHandler;
|
||||||
_addTestAuthentication = addTestAuthentication;
|
_addTestAuthentication = addTestAuthentication;
|
||||||
|
_instanceDatabaseName = instanceDatabaseName;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||||
@ -43,14 +40,22 @@ public sealed class CleanArchitectureWebApplicationFactory : WebApplicationFacto
|
|||||||
|
|
||||||
base.ConfigureWebHost(builder);
|
base.ConfigureWebHost(builder);
|
||||||
|
|
||||||
_connection.Open();
|
builder.ConfigureAppConfiguration(configurationBuilder =>
|
||||||
|
{
|
||||||
|
configurationBuilder.AddEnvironmentVariables();
|
||||||
|
|
||||||
|
var accessor = DatabaseAccessor.GetOrCreateAsync(_instanceDatabaseName);
|
||||||
|
|
||||||
|
// Overwrite default connection string to our test instance db
|
||||||
|
configurationBuilder.AddInMemoryCollection([
|
||||||
|
new KeyValuePair<string, string?>(
|
||||||
|
"ConnectionStrings:DefaultConnection",
|
||||||
|
accessor.GetConnectionString())
|
||||||
|
]);
|
||||||
|
});
|
||||||
|
|
||||||
builder.ConfigureServices(services =>
|
builder.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
services.SetupTestDatabase<ApplicationDbContext>(_connection);
|
|
||||||
services.SetupTestDatabase<EventStoreDbContext>(_connection);
|
|
||||||
services.SetupTestDatabase<DomainNotificationStoreDbContext>(_connection);
|
|
||||||
|
|
||||||
if (_addTestAuthentication)
|
if (_addTestAuthentication)
|
||||||
{
|
{
|
||||||
services.AddAuthentication(options =>
|
services.AddAuthentication(options =>
|
||||||
@ -65,22 +70,22 @@ public sealed class CleanArchitectureWebApplicationFactory : WebApplicationFacto
|
|||||||
using var scope = sp.CreateScope();
|
using var scope = sp.CreateScope();
|
||||||
var scopedServices = scope.ServiceProvider;
|
var scopedServices = scope.ServiceProvider;
|
||||||
|
|
||||||
var applicationDbContext = scopedServices.GetRequiredService<ApplicationDbContext>();
|
var accessor = DatabaseAccessor.GetOrCreateAsync(_instanceDatabaseName);
|
||||||
var storeDbContext = scopedServices.GetRequiredService<EventStoreDbContext>();
|
var applicationDbContext = accessor.CreateDatabase(scopedServices);
|
||||||
var domainStoreDbContext = scopedServices.GetRequiredService<DomainNotificationStoreDbContext>();
|
|
||||||
|
|
||||||
applicationDbContext.EnsureMigrationsApplied();
|
|
||||||
|
|
||||||
var creator2 = (RelationalDatabaseCreator)storeDbContext.Database
|
|
||||||
.GetService<IRelationalDatabaseCreator>();
|
|
||||||
creator2.CreateTables();
|
|
||||||
|
|
||||||
var creator3 = (RelationalDatabaseCreator)domainStoreDbContext
|
|
||||||
.Database.GetService<IRelationalDatabaseCreator>();
|
|
||||||
creator3.CreateTables();
|
|
||||||
|
|
||||||
_addCustomSeedDataHandler?.Invoke(applicationDbContext);
|
|
||||||
_registerCustomServicesHandler?.Invoke(services, sp, scopedServices);
|
_registerCustomServicesHandler?.Invoke(services, sp, scopedServices);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task RespawnDatabaseAsync()
|
||||||
|
{
|
||||||
|
var accessor = DatabaseAccessor.GetOrCreateAsync(_instanceDatabaseName);
|
||||||
|
await accessor.RespawnDatabaseAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async ValueTask DisposeAsync()
|
||||||
|
{
|
||||||
|
var accessor = DatabaseAccessor.GetOrCreateAsync(_instanceDatabaseName);
|
||||||
|
await accessor.DisposeAsync();
|
||||||
|
}
|
||||||
}
|
}
|
@ -0,0 +1,125 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using CleanArchitecture.Infrastructure.Database;
|
||||||
|
using CleanArchitecture.Infrastructure.Extensions;
|
||||||
|
using Microsoft.Data.SqlClient;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Respawn;
|
||||||
|
using Testcontainers.MsSql;
|
||||||
|
|
||||||
|
namespace CleanArchitecture.IntegrationTests.Infrastructure;
|
||||||
|
|
||||||
|
public sealed class DatabaseAccessor
|
||||||
|
{
|
||||||
|
private static readonly ConcurrentDictionary<string, DatabaseAccessor> s_accessors = new();
|
||||||
|
|
||||||
|
private readonly string _instanceDatabaseName;
|
||||||
|
private bool _databaseCreated = false;
|
||||||
|
private readonly object _databaseCreationLock = new();
|
||||||
|
|
||||||
|
private const string _dbPassword = "12345678##as";
|
||||||
|
private static readonly MsSqlContainer s_dbContainer = new MsSqlBuilder()
|
||||||
|
.WithPassword(_dbPassword)
|
||||||
|
.WithPortBinding(1433)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
public DatabaseAccessor(string instanceName)
|
||||||
|
{
|
||||||
|
_instanceDatabaseName = instanceName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task InitializeAsync()
|
||||||
|
{
|
||||||
|
await s_dbContainer.StartAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public ApplicationDbContext CreateDatabase(IServiceProvider scopedServices)
|
||||||
|
{
|
||||||
|
var applicationDbContext = scopedServices.GetRequiredService<ApplicationDbContext>();
|
||||||
|
|
||||||
|
lock (_databaseCreationLock)
|
||||||
|
{
|
||||||
|
if (_databaseCreated)
|
||||||
|
{
|
||||||
|
return applicationDbContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
applicationDbContext.EnsureMigrationsApplied();
|
||||||
|
|
||||||
|
var eventsContext = scopedServices.GetRequiredService<EventStoreDbContext>();
|
||||||
|
eventsContext.EnsureMigrationsApplied();
|
||||||
|
|
||||||
|
var notificationsContext = scopedServices.GetRequiredService<DomainNotificationStoreDbContext>();
|
||||||
|
notificationsContext.EnsureMigrationsApplied();
|
||||||
|
}
|
||||||
|
|
||||||
|
_databaseCreated = true;
|
||||||
|
|
||||||
|
return applicationDbContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
public async ValueTask DisposeAsync()
|
||||||
|
{
|
||||||
|
var dropScript = $@"
|
||||||
|
USE MASTER;
|
||||||
|
|
||||||
|
ALTER DATABASE [{_instanceDatabaseName}]
|
||||||
|
SET multi_user WITH ROLLBACK IMMEDIATE;
|
||||||
|
|
||||||
|
ALTER DATABASE [{_instanceDatabaseName}]
|
||||||
|
SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
|
||||||
|
|
||||||
|
DROP DATABASE [{_instanceDatabaseName}];";
|
||||||
|
|
||||||
|
await using (var con = new SqlConnection(GetConnectionString()))
|
||||||
|
{
|
||||||
|
await con.OpenAsync();
|
||||||
|
|
||||||
|
var cmd = new SqlCommand(dropScript, con);
|
||||||
|
await cmd.ExecuteNonQueryAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
await s_dbContainer.DisposeAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task RespawnDatabaseAsync()
|
||||||
|
{
|
||||||
|
var connectionString = GetConnectionString();
|
||||||
|
|
||||||
|
var respawn = await Respawner.CreateAsync(
|
||||||
|
connectionString,
|
||||||
|
new RespawnerOptions
|
||||||
|
{
|
||||||
|
TablesToIgnore = ["__EFMigrationsHistory"]
|
||||||
|
});
|
||||||
|
|
||||||
|
await respawn.ResetAsync(connectionString);
|
||||||
|
}
|
||||||
|
|
||||||
|
public string GetConnectionString()
|
||||||
|
{
|
||||||
|
var conBuilder = new SqlConnectionStringBuilder()
|
||||||
|
{
|
||||||
|
DataSource = s_dbContainer.Hostname,
|
||||||
|
InitialCatalog = _instanceDatabaseName,
|
||||||
|
IntegratedSecurity = false,
|
||||||
|
Password = _dbPassword,
|
||||||
|
UserID = "sa",
|
||||||
|
TrustServerCertificate = true
|
||||||
|
};
|
||||||
|
|
||||||
|
return conBuilder.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DatabaseAccessor GetOrCreateAsync(string instanceName)
|
||||||
|
{
|
||||||
|
if (!s_accessors.TryGetValue(instanceName, out _))
|
||||||
|
{
|
||||||
|
var accessor = new DatabaseAccessor(instanceName);
|
||||||
|
s_accessors.TryAdd(instanceName, accessor);
|
||||||
|
}
|
||||||
|
|
||||||
|
return s_accessors[instanceName];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,10 @@
|
|||||||
|
using CleanArchitecture.IntegrationTests.Fixtures;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace CleanArchitecture.IntegrationTests;
|
||||||
|
|
||||||
|
[CollectionDefinition("IntegrationTests", DisableParallelization = true)]
|
||||||
|
public sealed class IntegrationTestsCollection :
|
||||||
|
ICollectionFixture<DatabaseFixture>
|
||||||
|
{
|
||||||
|
}
|
@ -5,9 +5,12 @@ using CleanArchitecture.IntegrationTests.Fixtures.gRPC;
|
|||||||
using CleanArchitecture.Proto.Tenants;
|
using CleanArchitecture.Proto.Tenants;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using Xunit.Priority;
|
||||||
|
|
||||||
namespace CleanArchitecture.IntegrationTests.gRPC;
|
namespace CleanArchitecture.IntegrationTests.gRPC;
|
||||||
|
|
||||||
|
[Collection("IntegrationTests")]
|
||||||
|
[TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)]
|
||||||
public sealed class GetTenantsByIdsTests : IClassFixture<GetTenantsByIdsTestFixture>
|
public sealed class GetTenantsByIdsTests : IClassFixture<GetTenantsByIdsTestFixture>
|
||||||
{
|
{
|
||||||
private readonly GetTenantsByIdsTestFixture _fixture;
|
private readonly GetTenantsByIdsTestFixture _fixture;
|
||||||
|
@ -4,9 +4,12 @@ using CleanArchitecture.IntegrationTests.Fixtures.gRPC;
|
|||||||
using CleanArchitecture.Proto.Users;
|
using CleanArchitecture.Proto.Users;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
using Xunit.Priority;
|
||||||
|
|
||||||
namespace CleanArchitecture.IntegrationTests.gRPC;
|
namespace CleanArchitecture.IntegrationTests.gRPC;
|
||||||
|
|
||||||
|
[Collection("IntegrationTests")]
|
||||||
|
[TestCaseOrderer(PriorityOrderer.Name, PriorityOrderer.Assembly)]
|
||||||
public sealed class GetUsersByIdsTests : IClassFixture<GetUsersByIdsTestFixture>
|
public sealed class GetUsersByIdsTests : IClassFixture<GetUsersByIdsTestFixture>
|
||||||
{
|
{
|
||||||
private readonly GetUsersByIdsTestFixture _fixture;
|
private readonly GetUsersByIdsTestFixture _fixture;
|
||||||
|
Loading…
Reference in New Issue
Block a user