Testcontainers Node Documentation

repository·main·Indexed 25 days ago

https://github.com/testcontainers/testcontainers-node

A library for managing Docker containers within Node.js applications to provide ephemeral, reproducible environments for integration testing. It includes features for managing GenericContainers, Docker Compose environments via DockerComposeEnvironment, and low-level access to container runtimes like Docker, Podman, and Colima through the ContainerRuntimeClient.

Tokens
58.1K
Snippets
158
Records
545
Agent score
82%

What's inside Testcontainers Node

  1. What is Testcontainers for Node.js

    main
    Testcontainers is a library designed to support automated testing by providing lightweight, throwaway instances of common dependencies. It allows you to run databases, Selenium web browsers, or any other software that can run in a Docker container as part of your test lifecycle.
  2. Overview of Testcontainers Node

    main
    Testcontainers is a library that provides lightweight, throwaway instances of common databases, instruction sets, or anything else that can run in a Docker container. It allows developers to manage the lifecycle of these containers (start, stop, etc.) directly from their code, making it ideal for integration testing.
  3. Use @testcontainers/azurite for Azure Storage emulation

    main

    The @testcontainers/azurite module allows you to run an Azurite container for testing Azure Blob, Queue, and Table storage.

    Common usage patterns include:

    • Blob Storage: Uploading and downloading blobs.
    • Queue Storage: Sending and receiving queue messages.
    • Table Storage: Creating, inserting, and fetching data from tables.
    • Persistence: Using in-memory persistence for testing.
    • Security: Configuring custom credentials, HTTPS with PEM certificates, or OAuth.
    • Networking: Mapping custom ports.

    Note: When implementing, you may need to substitute IMAGE with a specific image from the Microsoft Azurite container registry.

  4. Use MongoDBAtlasLocalContainer

    main

    The MongoDBAtlasLocalContainer provides a MongoDB Atlas Local image, which combines the MongoDB database engine with MongoT for Atlas Search capabilities.

    Important Note: The connection string returned by getConnectionString() does not include directConnection=true. When connecting with a MongoDB client, you must manually pass directConnection: true in your client options.

  5. Reuse containers across tests

    main

    Enabling container re-use allows Testcontainers to skip starting a new container if a container with the exact same configuration is already running. This is useful for sharing a container across multiple tests without global setup.

    To enable re-use, call .withReuse() on your container instance. You can also re-use stopped containers if you set .withAutoRemove(false) before stopping them.

    Global control: You can enable or disable this feature globally using the TESTCONTAINERS_REUSE_ENABLE environment variable. If not set, the feature is enabled by default.

    const container1 = await new GenericContainer("alpine")
      .withCommand(["sleep", "infinity"])
      .withReuse()
      .start();
    
    const container2 = await new GenericContainer("alpine")
      .withCommand(["sleep", "infinity"])
      .withReuse()
      .start();
    
    expect(container1.getId()).toBe(container2.getId());
  6. Share container data with tests using inject()

    main

    Because globalSetup runs in a different global scope than your individual test files, you cannot directly access variables defined in the setup script. To share data (like connection URLs), use the project.provide(key, value) method in your setup script and retrieve it using the inject(key) function within your tests. The values provided must be serializable.

    import { afterAll, beforeAll, expect, inject, test } from "vitest";
    import { createClient } from "redis";
    
    // Retrieve the URL provided by the global setup
    const redisClient = createClient({ url: inject("redisUrl") });
    
    beforeAll(async () => {
      await redisClient.connect();
    });
    
    afterAll(async () => {
      await redisClient.disconnect();
    });
    
    test("stores and reads a value", async () => {
      await redisClient.set("key", "test-value");
      const result = await redisClient.get("key");
      expect(result).toBe("test-value");
    });
  7. Understand default wait strategies

    main

    Testcontainers uses a default selection logic for waiting:

    1. Health Check: If the image defines a health check or you use .withHealthCheck(), Testcontainers waits for that health check to succeed.
    2. Listening Ports: If no health check is defined (or if the image uses HEALTHCHECK NONE), Testcontainers waits up to 60 seconds for mapped network ports to be bound.

    You can override this behavior using .withWaitStrategy().

  8. Compose multiple wait strategies

    main

    You can chain multiple strategies together using Wait.forAll([...]).

    • Timeouts: Each inner strategy respects its own .withStartupTimeout(). If an inner strategy doesn't have one, it inherits the timeout set on the composite via .withStartupTimeout().
    • Deadlines: You can use .withDeadline(ms) on the composite strategy. The composite will throw an error unless all inner strategies resolve before this deadline.
    const { GenericContainer, Wait } = require("testcontainers");
    
    // Wait for both ports AND a log message
    const container = await new GenericContainer("alpine")
      .withWaitStrategy(Wait.forAll([
        Wait.forListeningPorts(), 
        Wait.forLogMessage("Ready to accept connections")
      ]))
      .start();
    
    // Using a deadline for the entire composite
    const compositeWithDeadline = Wait.forAll([Wait.forListeningPorts(), Wait.forLogMessage("READY")])
      .withDeadline(2000);
  9. Start a container with GenericContainer

    main

    Use GenericContainer to create and start any Docker container. You can specify the image name and version directly in the constructor.

    Note: Testcontainers automatically pulls images if they are not present locally, but you can configure the pull policy.

    const { GenericContainer } = require("testcontainers");
    
    // Start a container with default image
    const container = await new GenericContainer("alpine").start();
    
    // Start a container with a specific version
    const container = await new GenericContainer("alpine:3.10").start();