DEV Community

Cover image for πŸš€ Level up your testing game with TestContainers
Yashodhan Singh
Yashodhan Singh

Posted on

πŸš€ Level up your testing game with TestContainers

As software developers, writing tests is an important part of our daily routine. We need to make sure our code works as expected and can handle different scenarios. One important aspect of testing is to make sure our code interacts with databases correctly. However, testing with a real database can be a challenge. It can be time-consuming to set up, difficult to manage, and may have unintended consequences.

That's where TestContainers comes in! πŸŽ‰

TestContainers is an open-source library that allows you to run containers for your tests. With TestContainers, you can spin up a database container in seconds, run your tests, and dispose of the container. It eliminates the hassle of setting up a real database, and ensures that your tests are isolated and repeatable.

Let's see how we can use TestContainers to test our code that interacts with databases.

πŸ’‘ Simple Example:

Let's start with a simple example. We'll use TestContainers to run a PostgreSQL database and write tests to insert and retrieve data from the database. First, we need to install TestContainers and the PostgreSQL client:

npm install --save-dev testcontainers jest pg
Enter fullscreen mode Exit fullscreen mode

Next, let's write the tests:

const { GenericContainer } = require('testcontainers');
const Client = require('pg').Client;

describe('Test database', () => {
  let client;
  let container;

  beforeAll(async () => {
    container = await new GenericContainer('postgres', '12')
      .withEnv('POSTGRES_USER', 'postgres')
      .withEnv('POSTGRES_PASSWORD', 'secret')
      .withExposedPorts(5432)
      .start();

    const host = await container.getContainerIpAddress();
    const port = container.getMappedPort(5432);
    const password = 'secret';
    const database = 'testdb';

    client = new Client({
      host,
      port,
      user: 'postgres',
      password,
      database,
    });

    await client.connect();
  });

  afterAll(async () => {
    await client.end();
    await container.stop();
  });

  test('Insert data into the database', async () => {
    await client.query('CREATE TABLE test (id serial, message text)');
    const res = await client.query("INSERT INTO test (message) values ('hello world')");
    expect(res.rowCount).toBe(1);
  });

  test('Retrieve data from the database', async () => {
    const res = await client.query('SELECT * FROM test');
    expect(res.rows[0].message).toBe('hello world');
  });
});

Enter fullscreen mode Exit fullscreen mode

In this example, we use the beforeAll hook to start the PostgreSQL container and connect to the database. The afterAll hook stops the container and closes the connection. In the tests, we use the client to interact with the database.

πŸŽ‰ Conclusion:

TestContainers is a fantastic tool for testing code that interacts with databases. It makes it easy to spin up a container, run your tests, and dispose of the container. With TestContainers, you can ensure that your tests are isolated, repeatable, and fast. Give it a try, and level up your testing game! πŸš€

Check out the TestContainers library here: TestContainers on GitHub

Let me know if you have any questions or feedback! 😊

Top comments (0)