CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nestjs--testing

Comprehensive testing utilities for NestJS applications with dependency injection testing capabilities

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

application-testing.mddocs/

Application Testing

Create full NestJS applications and microservices from test modules for end-to-end testing scenarios. This capability allows developers to test complete application behavior, including HTTP endpoints, WebSocket connections, and microservice communication.

Capabilities

NestJS Application Creation

Create full HTTP applications from testing modules for integration and end-to-end testing.

class TestingModule extends NestApplicationContext {
  /**
   * Create a NestJS HTTP application with default Express adapter
   * @param options - Optional application configuration
   * @returns NestJS application instance
   */
  createNestApplication<T extends INestApplication = INestApplication>(
    options?: NestApplicationOptions
  ): T;

  /**
   * Create a NestJS HTTP application with custom HTTP adapter
   * @param httpAdapter - Custom HTTP server or adapter
   * @param options - Optional application configuration
   * @returns NestJS application instance
   */
  createNestApplication<T extends INestApplication = INestApplication>(
    httpAdapter: HttpServer | AbstractHttpAdapter,
    options?: NestApplicationOptions
  ): T;
}

Usage Examples:

import { Test, TestingModule } from "@nestjs/testing";
import { INestApplication } from "@nestjs/common";
import * as request from "supertest";
import { AppModule } from "./app.module";

describe("Application E2E Testing", () => {
  let app: INestApplication;
  let module: TestingModule;

  beforeAll(async () => {
    module = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = module.createNestApplication();
    await app.init();
  });

  afterAll(async () => {
    await app.close();
    await module.close();
  });

  it("should handle GET /users", async () => {
    const response = await request(app.getHttpServer())
      .get("/users")
      .expect(200);
      
    expect(response.body).toBeInstanceOf(Array);
  });

  it("should handle POST /users", async () => {
    const newUser = { name: "John Doe", email: "john@example.com" };
    
    const response = await request(app.getHttpServer())
      .post("/users")
      .send(newUser)
      .expect(201);
      
    expect(response.body.id).toBeDefined();
  });
});

Custom HTTP Adapter

Use custom HTTP adapters for specific testing scenarios:

import { FastifyAdapter } from "@nestjs/platform-fastify";
import { ExpressAdapter } from "@nestjs/platform-express";
import * as express from "express";

// Using Fastify adapter
const fastifyModule = await Test.createTestingModule({
  imports: [AppModule],
}).compile();

const fastifyApp = fastifyModule.createNestApplication(
  new FastifyAdapter()
);

await fastifyApp.init();
await fastifyApp.getHttpAdapter().getInstance().ready();

// Using custom Express instance
const expressServer = express();
const expressModule = await Test.createTestingModule({
  imports: [AppModule],
}).compile();

const expressApp = expressModule.createNestApplication(
  new ExpressAdapter(expressServer)
);

await expressApp.init();

// Testing with the custom server
const response = await request(expressServer)
  .get("/health")
  .expect(200);

Application Configuration

Configure applications with specific options for testing:

import { ValidationPipe, Logger } from "@nestjs/common";

const module = await Test.createTestingModule({
  imports: [AppModule],
}).compile();

const app = module.createNestApplication({
  logger: false, // Disable logging for tests
  cors: true,    // Enable CORS for testing
  bodyParser: true,
});

// Configure global pipes, filters, interceptors
app.useGlobalPipes(new ValidationPipe({
  transform: true,
  whitelist: true,
}));

// Configure custom headers or middleware
app.use((req, res, next) => {
  res.setHeader("X-Test-Mode", "true");
  next();
});

await app.init();

Microservice Creation

Create microservices for testing distributed system scenarios:

class TestingModule extends NestApplicationContext {
  /**
   * Create a NestJS microservice instance
   * @param options - Microservice configuration including transport and options
   * @returns NestJS microservice instance
   */
  createNestMicroservice<T extends object>(
    options: NestMicroserviceOptions & T
  ): INestMicroservice;
}

Usage Examples:

import { Test, TestingModule } from "@nestjs/testing";
import { INestMicroservice, Transport } from "@nestjs/microservices";
import { MicroserviceModule } from "./microservice.module";

describe("Microservice Testing", () => {
  let microservice: INestMicroservice;
  let module: TestingModule;

  beforeAll(async () => {
    module = await Test.createTestingModule({
      imports: [MicroserviceModule],
    }).compile();

    microservice = module.createNestMicroservice({
      transport: Transport.TCP,
      options: {
        port: 8877,
      },
    });

    await microservice.listen();
  });

  afterAll(async () => {
    await microservice.close();
    await module.close();
  });

  it("should process messages", async () => {
    // Test microservice message handling
    const result = await microservice
      .send({ cmd: "get_user" }, { id: 1 })
      .toPromise();
      
    expect(result).toBeDefined();
  });
});

Redis Microservice Testing

// Redis microservice testing
const redisModule = await Test.createTestingModule({
  imports: [RedisModule],
}).compile();

const redisMicroservice = redisModule.createNestMicroservice({
  transport: Transport.REDIS,
  options: {
    host: "localhost",
    port: 6379,
  },
});

await redisMicroservice.listen();

// Test Redis pub/sub patterns

RMQ Microservice Testing

// RabbitMQ microservice testing
const rmqModule = await Test.createTestingModule({
  imports: [RmqModule],
}).compile();

const rmqMicroservice = rmqModule.createNestMicroservice({
  transport: Transport.RMQ,
  options: {
    urls: ["amqp://localhost:5672"],
    queue: "test_queue",
    queueOptions: {
      durable: false,
    },
  },
});

await rmqMicroservice.listen();

WebSocket Testing

Test WebSocket gateways and real-time functionality:

import { Test } from "@nestjs/testing";
import { INestApplication } from "@nestjs/common";
import { Socket, io } from "socket.io-client";
import { ChatModule } from "./chat.module";

describe("WebSocket Gateway", () => {
  let app: INestApplication;
  let client: Socket;

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [ChatModule],
    }).compile();

    app = module.createNestApplication();
    await app.init();
    await app.listen(3001);

    client = io("http://localhost:3001");
  });

  afterAll(async () => {
    client.close();
    await app.close();
  });

  it("should handle message events", (done) => {
    client.emit("message", { text: "Hello World" });
    
    client.on("message", (data) => {
      expect(data.text).toBe("Hello World");
      done();
    });
  });
});

GraphQL Testing

Test GraphQL APIs with schema validation:

import { Test } from "@nestjs/testing";
import { GraphQLModule } from "@nestjs/graphql";
import * as request from "supertest";

describe("GraphQL API", () => {
  let app: INestApplication;

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [
        GraphQLModule.forRoot({
          autoSchemaFile: true,
          playground: false,
        }),
        UsersModule,
      ],
    }).compile();

    app = module.createNestApplication();
    await app.init();
  });

  it("should execute GraphQL queries", async () => {
    const query = `
      query {
        users {
          id
          name
          email
        }
      }
    `;

    const response = await request(app.getHttpServer())
      .post("/graphql")
      .send({ query })
      .expect(200);

    expect(response.body.data.users).toBeInstanceOf(Array);
  });

  it("should handle GraphQL mutations", async () => {
    const mutation = `
      mutation {
        createUser(input: { name: "John", email: "john@example.com" }) {
          id
          name
          email
        }
      }
    `;

    const response = await request(app.getHttpServer())
      .post("/graphql")
      .send({ query: mutation })
      .expect(200);

    expect(response.body.data.createUser.id).toBeDefined();
  });
});

Application Lifecycle Management

Handle application startup and shutdown properly in tests:

describe("Application Lifecycle", () => {
  let app: INestApplication;

  beforeEach(async () => {
    const module = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = module.createNestApplication();
    
    // Enable shutdown hooks for graceful shutdown
    app.enableShutdownHooks();
    
    await app.init();
  });

  afterEach(async () => {
    // Ensure proper cleanup
    await app?.close();
  });

  it("should handle graceful shutdown", async () => {
    await app.listen(3002);
    
    // Simulate shutdown signal
    process.emit("SIGTERM");
    
    // Application should close gracefully
    await new Promise((resolve) => setTimeout(resolve, 1000));
  });
});

Error Handling in Applications

Test error handling and exception filters:

import { ExceptionFilter, ArgumentsHost, Catch } from "@nestjs/common";

@Catch()
class TestExceptionFilter implements ExceptionFilter {
  catch(exception: any, host: ArgumentsHost) {
    const response = host.switchToHttp().getResponse();
    response.status(500).json({
      error: "Test error",
      message: exception.message,
    });
  }
}

describe("Error Handling", () => {
  let app: INestApplication;

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [AppModule],
    }).compile();

    app = module.createNestApplication();
    app.useGlobalFilters(new TestExceptionFilter());
    
    await app.init();
  });

  it("should handle application errors", async () => {
    const response = await request(app.getHttpServer())
      .get("/error-endpoint")
      .expect(500);

    expect(response.body.error).toBe("Test error");
  });
});

Types

import {
  INestApplication,
  INestMicroservice,
  NestApplicationOptions,
  HttpServer,
} from "@nestjs/common";
import { AbstractHttpAdapter } from "@nestjs/core";
import { NestMicroserviceOptions } from "@nestjs/common/interfaces/microservices/nest-microservice-options.interface";

interface NestApplicationOptions {
  logger?: LoggerService | LogLevel[] | false;
  cors?: boolean | CorsOptions;
  bodyParser?: boolean;
  httpsOptions?: HttpsOptions;
  rawBody?: boolean;
  defaultGlobalPrefix?: string;
  snapshot?: boolean;
  preview?: boolean;
}

interface NestMicroserviceOptions {
  transport?: Transport;
  options?: any;
  logger?: LoggerService | LogLevel[] | false;
  snapshot?: boolean;
  preview?: boolean;
}

docs

application-testing.md

index.md

mock-integration.md

module-building.md

module-overriding.md

provider-overriding.md

tile.json