Skip to content

Instantly share code, notes, and snippets.

@ali-kamalizade
Last active September 16, 2022 21:03
Show Gist options
  • Save ali-kamalizade/f4347dc53ac59bdfbed0131ca710fcda to your computer and use it in GitHub Desktop.
Save ali-kamalizade/f4347dc53ac59bdfbed0131ca710fcda to your computer and use it in GitHub Desktop.
A function to create a Postgres container with Testcontainers. Written in TypeScript.
import { GenericContainer, StartedTestContainer } from 'testcontainers';
import { AbstractStartedContainer } from 'testcontainers/dist/modules/abstract-started-container';
import { RandomUuid } from 'testcontainers/dist/uuid';
const POSTGRES_PORT = 5432;
export async function createDatabaseContainer() {
// reusing the same container for all tests is considerably faster than starting a new one for each test
const container = await new PostgreSqlContainer().withReuse().start();
const host = container.getHost();
const port = container.getPort();
const database = container.getDatabase();
const user = container.getUsername();
const password = container.getPassword();
// needed later to retrieve the current container, so it can be stopped and removed after the tests have run
process.env.TEST_POSTGRES_CONTAINER_ID = container.getId();
// the database client (e.g. Prisma) uses this to connect to the database
process.env.POSTGRES_DATABASE_URL = `postgresql://${user}:${password}@${host}:${port}/${database}?schema=public`;
// do anything else: e.g. run database migrations
return container;
}
export class PostgreSqlContainer extends GenericContainer {
private database = 'test';
private username = new RandomUuid().nextUuid();
private password = new RandomUuid().nextUuid();
constructor(readonly image = 'postgres:14.2-alpine') {
super(image);
}
public async start(): Promise<StartedPostgreSqlContainer> {
this.withExposedPorts(...(this.hasExposedPorts ? this.ports : [POSTGRES_PORT]))
.withEnv('POSTGRES_DB', this.database)
.withEnv('POSTGRES_USER', this.username)
.withEnv('POSTGRES_PASSWORD', this.password)
.withStartupTimeout(120_000);
return new StartedPostgreSqlContainer(await super.start(), this.database, this.username, this.password);
}
}
export class StartedPostgreSqlContainer extends AbstractStartedContainer {
private readonly port: number;
constructor(
readonly startedTestContainer: StartedTestContainer,
private readonly database: string,
private readonly username: string,
private readonly password: string
) {
super(startedTestContainer);
this.port = startedTestContainer.getMappedPort(POSTGRES_PORT);
}
public getPort() {
return this.port;
}
public getDatabase() {
return this.database;
}
public getUsername() {
return this.username;
}
public getPassword() {
return this.password;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment