Skip to content

Instantly share code, notes, and snippets.

@joanna-liana
Last active December 23, 2023 01:43
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save joanna-liana/18d8f4cb95ecfb9efd12266937b1f27e to your computer and use it in GitHub Desktop.
Save joanna-liana/18d8f4cb95ecfb9efd12266937b1f27e to your computer and use it in GitHub Desktop.
Jest + TypeORM + TestContainers
import { setupTypeOrmTestConnection } from '../integrationSetup';
beforeAll(async () => {
console.log('AFTER ENV SETUP START');
global.testConn = await setupTypeOrmTestConnection(+process.env.TEST_PG_PORT);
console.log('AFTER ENV SETUP DONE');
});
afterAll(async () => {
console.log('AFTER ENV TEARDOWN START');
await global.testConn.close();
console.log('AFTER ENV TEARDOWN DONE');
});
import { setupTestPostgres } from '../integrationSetup';
module.exports = async () => {
console.log('\nGLOBAL SETUP START');
const { port, container } = await setupTestPostgres();
global.testPgContainer = container;
process.env.TEST_PG_PORT = `${port}`;
console.log('GLOBAL SETUP END');
};
module.exports = async () => {
console.log('GLOBAL TEARDOWN START');
await global.testPgContainer.stop();
console.log('GLOBAL TEARDOWN END');
};
import 'reflect-metadata';
import { GenericContainer, StartedTestContainer } from 'testcontainers';
import { ConnectionOptions, Connection, createConnection } from 'typeorm';
import { connectionOptions } from '../../infra/db';
const TEST_DB_NAME = 'playground_test';
const PG_USER = 'postgres';
export interface TestContainerData {
container: StartedTestContainer;
port: number;
}
export const setupTestPostgres = async (): Promise<TestContainerData> => {
const PG_PORT = 5432;
const pgContainer = new GenericContainer('postgres', '12.1')
.withExposedPorts(PG_PORT)
.withEnv('POSTGRES_USER', PG_USER)
.withEnv('POSTGRES_DB', TEST_DB_NAME);
const pgContainerStarted = await pgContainer.start();
const containerPort = pgContainerStarted.getMappedPort(PG_PORT);
console.log(`test Postgres port: ${containerPort}`);
return {
container: pgContainerStarted,
port: containerPort,
};
};
export const setupTypeOrmTestConnection = async (pgPort?: number): Promise<Connection> => {
let port = pgPort as number;
if (!pgPort) {
const { port: containerPort } = await setupTestPostgres();
port = containerPort;
}
const opts = getTestDatabaseConnectionOptions(port);
const connection = await createConnection(opts);
await connection.runMigrations();
return connection;
};
export const getTestDatabaseConnectionOptions = (
dbPort: number
): ConnectionOptions => ({
...connectionOptions,
host: 'localhost',
port: dbPort,
username: 'postgres',
password: 'postgres',
database: TEST_DB_NAME,
} as any);
module.exports = {
transform: {
'^.+\\.ts?$': '@swc/jest',
},
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.ts?$',
rootDir: '.',
collectCoverageFrom: ['**/*.ts', '!demo.ts'],
testTimeout: 1200000,
globalSetup: '<rootDir>/hooks/globalPostgresSetup.ts',
globalTeardown: '<rootDir>/hooks/globalPostgresTeardown.ts',
setupFilesAfterEnv: ['<rootDir>/hooks/afterEnv.ts']
};
import { StartedTestContainer } from 'testcontainers';
import { Connection } from 'typeorm';
// Ensure file is treated as a module
export { };
declare global {
namespace NodeJS {
interface Global {
testConn: Connection;
testPgContainer: StartedTestContainer;
}
}
}
{
// ...
"scripts": {
"test:unit": "jest --verbose ./src/test/unit/*.test.ts --config ./src/test/unit/jest.config.js",
"test:it": "jest --verbose --runInBand ./src/test/integration/suites/*.test.ts --config ./src/test/integration/jest.config.js"
},
"author": "Joanna Liana",
"license": "ISC",
"devDependencies": {
"@swc/jest": "^0.1.4",
"@types/jest": "^26.0.15",
"@types/node": "^8.10.66",
"jest": "^27.0.6",
"testcontainers": "^6.4.2",
"typescript": "^4.2.4"
},
"dependencies": {
"pg": "^8.6.0",
"reflect-metadata": "^0.1.10",
"typeorm": "0.2.31"
}
}
@joanna-liana
Copy link
Author

  • Single Postgres container for all tests
  • Works with the Jest Runner plugin

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment