-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathIntegrationTestBase.cs
More file actions
112 lines (99 loc) · 3.96 KB
/
Copy pathIntegrationTestBase.cs
File metadata and controls
112 lines (99 loc) · 3.96 KB
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using DotNet.Testcontainers.Builders;
using DotNet.Testcontainers.Configurations;
using DotNet.Testcontainers.Containers;
using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using ParcelTracking.Infrastructure.Data;
using Xunit;
namespace ParcelTracking.API.IntegrationTests
{
/// <summary>
/// Shared setup/teardown for integration tests that require a Postgres database.
///
/// - will honour the PARCELTRACK_TEST_DB environment variable if set,
/// otherwise it will start a disposable postgres container using
/// <see cref="DotNet.Testcontainers"/>.
/// - exposes <see cref="Client"/>, <see cref="Factory"/>, and
/// <see cref="ConnectionString"/> to derived tests.
/// </summary>
public abstract class IntegrationTestBase : IAsyncLifetime
{
protected WebApplicationFactory<Program>? Factory;
protected HttpClient? Client;
protected string? ConnectionString;
private PostgreSqlTestcontainer? _postgresContainer;
public virtual async Task InitializeAsync()
{
// check for an explicit connection string first
var env = Environment.GetEnvironmentVariable("PARCELTRACK_TEST_DB");
if (string.IsNullOrWhiteSpace(env))
{
try
{
// create and start a temporary postgres container
var builder = new TestcontainersBuilder<PostgreSqlTestcontainer>()
.WithDatabase(new PostgreSqlTestcontainerConfiguration
{
Database = "parceltracking_test",
Username = "test",
Password = "test"
})
.WithImage("postgres:15")
.WithCleanUp(true)
.WithPortBinding(5432, true);
_postgresContainer = builder.Build();
await _postgresContainer.StartAsync();
ConnectionString = _postgresContainer.ConnectionString;
}
catch
{
// Docker not available, skip tests
ConnectionString = null;
_postgresContainer = null;
}
}
else
{
ConnectionString = env;
}
if (ConnectionString == null)
return; // will cause tests to be skipped
// build the web app factory pointing at the test database
Factory = new WebApplicationFactory<Program>()
.WithWebHostBuilder(builder =>
{
builder.ConfigureAppConfiguration((context, cfg) =>
{
var inMemConfig = new Dictionary<string, string?>
{
{ "ConnectionStrings:DefaultConnection", ConnectionString }
};
cfg.AddInMemoryCollection(inMemConfig);
});
});
Client = Factory.CreateClient();
// ensure the database exists/migrated
var options = new DbContextOptionsBuilder<ParcelTrackingDbContext>()
.UseNpgsql(ConnectionString)
.Options;
await using var db = new ParcelTrackingDbContext(options);
await db.Database.EnsureCreatedAsync();
}
public virtual async Task DisposeAsync()
{
Client?.Dispose();
Factory?.Dispose();
if (_postgresContainer != null)
{
await _postgresContainer.StopAsync();
await _postgresContainer.DisposeAsync();
}
}
}
}