-
Notifications
You must be signed in to change notification settings - Fork 7
/
IntegrationTestsFixture.cs
84 lines (79 loc) · 3.4 KB
/
IntegrationTestsFixture.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
using System;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Storage;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Serilog;
using TicTacToeCSharpPlayground;
using TicTacToeCSharpPlayground.Infrastructure.Database;
namespace Tests.Support
{
public abstract class IntegrationTestsFixture<TStartup> : IDisposable where TStartup : class
{
protected readonly HttpClient Client;
protected readonly AppDbContext AppDbContext;
protected readonly IServiceProvider Services;
protected readonly string ConnectionString;
private readonly IDbContextTransaction _transaction;
protected IntegrationTestsFixture(Action<IServiceCollection> customSetup = null)
{
// Basic setup
var configuration = Program.BuildConfiguration();
var builder = WebHost.CreateDefaultBuilder().UseStartup<TStartup>().UseSerilog();
// Custom database per test method
var dbName = $"test_{Guid.NewGuid()}";
var oldDbValue = "Database=postgres;";
var newDbValue = $"Database={dbName};";
var connectionString = configuration.GetConnectionString("AppDbContext");
ConnectionString = connectionString.Replace(oldDbValue, newDbValue);
// https://github.com/dotnet/aspnetcore/issues/12079
builder.UseEnvironment("Production");
builder.ConfigureTestServices(ConfigureDatabaseAsSingleton(ConnectionString));
// You can create new clients with mocked services if required (see ConfigureTestServices)
if (customSetup is not null)
builder.ConfigureTestServices(customSetup);
var server = new TestServer(builder);
Services = server.Host.Services;
// It allows you to call API endpoints
Client = server.CreateClient();
// It allows you to consult the database
AppDbContext = Services.GetRequiredService<AppDbContext>();
Trace.Assert(AppDbContext.Database.GetDbConnection().Database == dbName);
ExecuteMissingMigrations();
// The transaction will be created by each test method, if you inherit it without an IClassFixture
_transaction = AppDbContext.Database.BeginTransaction();
}
private void ExecuteMissingMigrations()
{
AppDbContext.Database.EnsureCreated();
}
private Action<IServiceCollection> ConfigureDatabaseAsSingleton(string newConnectionString)
{
return services =>
{
services.RemoveAll<AppDbContext>();
services.RemoveAll<DbContextOptions<AppDbContext>>();
services.AddDbContext<AppDbContext>(options =>
{
options.UseNpgsql(newConnectionString);
}, ServiceLifetime.Singleton);
};
}
public void Dispose()
{
if (_transaction is not null)
{
_transaction.Rollback();
_transaction.Dispose();
}
AppDbContext.Database.EnsureDeleted();
}
}
}