From .NET Tests and Apps
pgembed keeps its instances where MysticMind.PostgresEmbed looks for named instances. A test that asks the library for InstanceName = "app" attaches in milliseconds when pgembed start app already runs it, and starts it itself when it does not. Only the process that started a server stops it, so tests leave your instance running.
These samples are an xUnit project that CI runs against real Postgres.
An xUnit fixture
csharp
snippet source | anchor// The "app" instance for a test run. If `pgembed start app` already runs it,
// the tests attach in milliseconds and leave it running; otherwise they start
// it, and stop it when they finish.
public sealed class AppDatabase : IAsyncLifetime
{
private readonly PgServer _server = new(new PgServerOptions
{
PgVersion = "17",
InstanceName = "app"
});
public string ConnectionString => _server.ConnectionString;
public async ValueTask InitializeAsync() => await _server.StartAsync();
public async ValueTask DisposeAsync() => await _server.DisposeAsync();
}csharp
snippet source | anchorpublic class BookTests(AppDatabase database) : IClassFixture<AppDatabase>
{
[Fact]
public async Task Stores_a_book()
{
await using var connection = new NpgsqlConnection(database.ConnectionString);
await connection.OpenAsync(TestContext.Current.CancellationToken);
await using var command = new NpgsqlCommand("""
CREATE TABLE IF NOT EXISTS books(id int PRIMARY KEY, title text);
INSERT INTO books VALUES (1, 'Dune') ON CONFLICT DO NOTHING;
SELECT title FROM books WHERE id = 1;
""", connection);
var title = await command.ExecuteScalarAsync(TestContext.Current.CancellationToken);
Assert.Equal("Dune", title);
}
}Every Postgres version
Start the instances once with pgembed start ci --version 16,17,18, or let each test start its own:
csharp
snippet source | anchor// `pgembed start ci --version 16,17,18` runs ci-16, ci-17 and ci-18;
// without it, each test starts its own
[Theory]
[InlineData("16")]
[InlineData("17")]
[InlineData("18")]
public async Task Runs_on_every_supported_major(string major)
{
await using var server = new PgServer(new PgServerOptions
{
PgVersion = major,
InstanceName = $"ci-{major}"
});
await server.StartAsync(TestContext.Current.CancellationToken);
await using var connection = new NpgsqlConnection(server.ConnectionString);
await connection.OpenAsync(TestContext.Current.CancellationToken);
Assert.StartsWith($"{major}.", connection.PostgreSqlVersion.ToString());
}From an app
Pass the connection string pgembed prints, here through configuration:
csharp
snippet source | anchor// set by: export ConnectionStrings__App="$(pgembed connstr app --format npgsql)"
var connectionString = Environment.GetEnvironmentVariable("ConnectionStrings__App");
await using var dataSource = NpgsqlDataSource.Create(connectionString!);
await using var command = dataSource.CreateCommand("SELECT current_database()");
var database = (string?)await command.ExecuteScalarAsync();pgembed connstr app prints it in every format: Npgsql, postgresql:// URI, libpq, JDBC, and PG* environment variables.
