Simulated environment

An environment to simulate an actual real-world scenario.

Well, before proceeding to the users tests, let's have a test database in order to test the CRUD operations. An actual Postgres database will be used so that the tests are closer to a real-world scenario. Environment variables will also be used for better organization.

We should then create the file .env.test.local, following the convention in the .gitignore file. There, copy the database credentials and just set the DATABASE_PORT to 5433, as to prevent a collision with the development database.

Once again in the docker-compose.yml file, create a service for the test database:

test-database:
  image: postgres
  restart: always
  ports:
    - ${DATABASE_PORT}:5432
  environment:
    POSTGRES_PASSWORD: ${DATABASE_PASSWORD}

And in the file package.json, let's add a pre and post scripts for test:e2e around it. They will be responsible for, respectively, creating and excluding the test database (and volume). Please note that we should also pass --env-file to indicate the .env file to be used in docker-compose.yml.

"pretest:e2e": "docker-compose --env-file .env.test.local up -d test-database",
"posttest:e2e": "docker-compose --env-file .env.test.local stop test-database && docker-compose --env-file .env.test.local rm -fv test-database",

Some notes:

  • We may also use the s flag for rm (resulting in -sfv), which would stop the container before removing, and allow for deleting the previous command for stopping (bit slower than the way shown above)

  • If the tests fail, the test database will need to be deleted manually with the post script

Inside the src folder, we can then create a configuration namespace for the test database in testing -> config -> test-database.config.

export default registerAs('testDatabase', () => {
  const user = process.env.DATABASE_USER;
  const password = process.env.DATABASE_PASSWORD;
  const host = process.env.DATABASE_HOST;
  const port = process.env.DATABASE_PORT;
  const name = process.env.DATABASE_NAME;

  const url = `postgresql://${user}:${password}@${host}:${port}/${name}`;

  const config = {
    type: 'postgres',
    url,
    autoLoadEntities: true,
    synchronize: true,
  } as const satisfies TypeOrmModuleOptions;
  return config;
});

Here, we turn on synchronize to automatically execute the migrations.

And we can create the file testing/util/testing.constants with the validation schema for the testing environment variables.

export const TEST_ENV_VALIDATION_SCHEMA = Joi.object({
  DATABASE_USER: Joi.required(),
  DATABASE_PASSWORD: Joi.required(),
  DATABASE_HOST: Joi.required(),
  DATABASE_PORT: Joi.number().port().required(),
  DATABASE_NAME: Joi.required(),
});

We may then proceed to the actual tests.

Last updated