I am trying to write integration tests for an expressjs application which uses TypeORM and a PostgreSQL database. The main application works fine without any issues with a main datasource, migrations works perfectly. The issue is with setting up integration test with testcontainers and another datasource which is really the same as the main datasource albeit getting it’s database connection parameters from the running testcontainer postressql instance.
One fascinating thing about this is that testing directly against the postgresql database on testcontainers passes. I believe the beforeAll hook is setup correctly:
describe('Get Test User From Test Database', () => {
it('Should get test user from test database', async () => {
const userRepository = testDataSource.getRepository(User);
const user = await userRepository.findOneBy({ id: "81528acc-160d-45a2-a2a0-dd7c0b9d70c8" });
expect(user).toBeDefined();
expect(user.email).toEqual("[email protected]");
expect(user.firstName).toEqual("Test");
expect(user.lastName).toEqual("User");
expect(user.phoneNumber).toEqual("+1234567890");
});
});
The tests that runs through the application fails with this error; EntityMetadataNotFoundError: No metadata for “User” was found
describe("User Routes", () => {
it("POST /api/v1/users - should create a user", async () => {
const response = await request(server.getServer())
.post("/api/v1/users").send({
email: "[email protected]",
password: "password123",
firstName: "Test",
lastName: "User",
phoneNumber: "1234567890",
});
expect(response.status).toBe(201);
});
});
This is the setup for testcontainers and datasource
export const createTestDataSource = async (): Promise<DataSource> => {
const pgContainer = await new PostgreSqlContainer('postgres:15.2-alpine')
.withDatabase('testdb')
.withUsername('testuser')
.withPassword('testpassword')
.withExposedPorts(5432)
.start();
const mappedPort = pgContainer.getMappedPort(5432);
const testDataSource = new DataSource({
type: 'postgres',
host: pgContainer.getHost(),
port: mappedPort,
username: pgContainer.getUsername(),
password: pgContainer.getPassword(),
database: pgContainer.getDatabase(),
migrations: ['src/database/migrations/*{.ts,.js}'],
migrationsTableName: 'migrations',
synchronize: false,
logging: false,
entities: [Booking, Event, User],
connectTimeoutMS: 30000,
uuidExtension: 'uuid-ossp',
});
await testDataSource.initialize();
await testDataSource.runMigrations();
return testDataSource;
}
I have tried writing a test case that just checks for a user directly against the postgresql database running on testcontainers and this passes. This is my beforeAll hook which inserts a test user into the database and this passes:
beforeAll(async () => {
try {
testDataSource = await createTestDataSource();
if (!testDataSource.hasMetadata(User)) {
throw new Error("User metadata not found in test database");
}
await testDataSource.getRepository(User).save({
id: "81528acc-160d-45a2-a2a0-dd7c0b9d70c8",
createdAt: new Date(),
updatedAt: new Date(),
deletedAt: null,
email: "[email protected]",
password: "password123",
firstName: "Test",
lastName: "User",
phoneNumber: "+1234567890",
});
const testDBservice = new DatabaseService(testDataSource);
server = new ExpressServer(testDBservice, mockCacheService);
await server.init();
} catch (error) {
console.error("Error during beforeAll setup:", error);
throw error;
}
});
greazleay is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.