mirror of
https://github.com/aliasvault/aliasvault.git
synced 2026-02-19 15:39:13 -05:00
165 lines
6.1 KiB
C#
165 lines
6.1 KiB
C#
// -----------------------------------------------------------------------
|
|
// <copyright file="AbstractTestHostBuilder.cs" company="aliasvault">
|
|
// Copyright (c) aliasvault. All rights reserved.
|
|
// Licensed under the AGPLv3 license. See LICENSE.md file in the project root for full license information.
|
|
// </copyright>
|
|
// -----------------------------------------------------------------------
|
|
|
|
namespace AliasVault.IntegrationTests;
|
|
|
|
using System.Reflection;
|
|
using AliasServerDb;
|
|
using AliasServerDb.Configuration;
|
|
using AliasVault.Logging;
|
|
using Microsoft.EntityFrameworkCore;
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using Microsoft.Extensions.Hosting;
|
|
using Npgsql;
|
|
|
|
/// <summary>
|
|
/// Builder class for creating a test host for services in order to run integration tests against them. This class
|
|
/// contains common logic such as creating a temporary database.
|
|
/// </summary>
|
|
public class AbstractTestHostBuilder : IAsyncDisposable
|
|
{
|
|
/// <summary>
|
|
/// The DbContextFactory instance that is created for the test.
|
|
/// </summary>
|
|
private IAliasServerDbContextFactory _dbContextFactory = null!;
|
|
|
|
/// <summary>
|
|
/// The cached DbContext instance that can be used during the test.
|
|
/// </summary>
|
|
private AliasServerDbContext? _dbContext;
|
|
|
|
/// <summary>
|
|
/// The temporary database name for the test.
|
|
/// </summary>
|
|
private string? _tempDbName;
|
|
|
|
/// <summary>
|
|
/// Returns the DbContext instance for the test. This can be used to seed the database with test data.
|
|
/// </summary>
|
|
/// <returns>AliasServerDbContext instance.</returns>
|
|
public AliasServerDbContext GetDbContext()
|
|
{
|
|
if (_dbContext != null)
|
|
{
|
|
return _dbContext;
|
|
}
|
|
|
|
_dbContext = _dbContextFactory.CreateDbContext();
|
|
return _dbContext;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the DbContext instance for the test. This can be used to seed the database with test data.
|
|
/// </summary>
|
|
/// <returns>AliasServerDbContext instance.</returns>
|
|
public async Task<AliasServerDbContext> GetDbContextAsync()
|
|
{
|
|
return await _dbContextFactory.CreateDbContextAsync();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disposes of the test host and cleans up the temporary database.
|
|
/// </summary>
|
|
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
|
public async ValueTask DisposeAsync()
|
|
{
|
|
if (_dbContext != null)
|
|
{
|
|
await _dbContext.DisposeAsync();
|
|
_dbContext = null;
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(_tempDbName))
|
|
{
|
|
// Create a connection to 'postgres' database to drop the test database
|
|
using var conn =
|
|
new NpgsqlConnection(
|
|
"Host=localhost;Port=5433;Database=postgres;Username=aliasvault;Password=password");
|
|
await conn.OpenAsync();
|
|
|
|
// First terminate existing connections
|
|
using (var cmd = conn.CreateCommand())
|
|
{
|
|
cmd.CommandText = $"""
|
|
SELECT pg_terminate_backend(pid)
|
|
FROM pg_stat_activity
|
|
WHERE datname = '{_tempDbName}';
|
|
""";
|
|
await cmd.ExecuteNonQueryAsync();
|
|
}
|
|
|
|
// Then drop the database
|
|
using (var cmd = conn.CreateCommand())
|
|
{
|
|
cmd.CommandText = $"""
|
|
DROP DATABASE IF EXISTS "{_tempDbName}";
|
|
""";
|
|
await cmd.ExecuteNonQueryAsync();
|
|
}
|
|
|
|
GC.SuppressFinalize(this);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Creates a new test host builder with test database connection already configured.
|
|
/// </summary>
|
|
/// <returns>IHost.</returns>
|
|
protected IHostBuilder CreateBuilder()
|
|
{
|
|
_tempDbName = $"aliasdb_test_{Guid.NewGuid()}";
|
|
|
|
// Create a connection to 'postgres' database to ensure the test database exists
|
|
AppContext.SetSwitch("Npgsql.EnableLegacyTimestampBehavior", true);
|
|
|
|
using (var conn = new NpgsqlConnection("Host=localhost;Port=5433;Database=postgres;Username=aliasvault;Password=password"))
|
|
{
|
|
conn.Open();
|
|
using (var cmd = conn.CreateCommand())
|
|
{
|
|
cmd.CommandText = $"""
|
|
CREATE DATABASE "{_tempDbName}";
|
|
""";
|
|
cmd.ExecuteNonQuery();
|
|
}
|
|
}
|
|
|
|
// Create a connection to the new test database
|
|
var dbConnection = new NpgsqlConnection($"Host=localhost;Port=5433;Database={_tempDbName};Username=aliasvault;Password=password");
|
|
|
|
var builder = Host.CreateDefaultBuilder()
|
|
.ConfigureServices((context, services) =>
|
|
{
|
|
// Override configuration
|
|
var configuration = new ConfigurationBuilder()
|
|
.AddJsonFile("appsettings.json", optional: true)
|
|
.AddInMemoryCollection(new Dictionary<string, string?>
|
|
{
|
|
["DatabaseProvider"] = "postgresql",
|
|
["ConnectionStrings:AliasServerDbContext"] = dbConnection.ConnectionString,
|
|
})
|
|
.Build();
|
|
|
|
services.AddSingleton<IConfiguration>(configuration);
|
|
services.AddAliasVaultDatabaseConfiguration(configuration);
|
|
services.ConfigureLogging(configuration, Assembly.GetExecutingAssembly().GetName().Name!, "logs");
|
|
|
|
// Ensure the in-memory database is populated with tables
|
|
var serviceProvider = services.BuildServiceProvider();
|
|
using (var scope = serviceProvider.CreateScope())
|
|
{
|
|
_dbContextFactory = scope.ServiceProvider.GetRequiredService<IAliasServerDbContextFactory>();
|
|
var dbContext = _dbContextFactory.CreateDbContext();
|
|
dbContext.Database.Migrate();
|
|
}
|
|
});
|
|
|
|
return builder;
|
|
}
|
|
}
|