Comprehensive testing utilities for NestJS applications with dependency injection testing capabilities
—
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Pending
The risk profile of this skill
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.
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();
});
});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);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();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
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// 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();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();
});
});
});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();
});
});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));
});
});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");
});
});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;
}