Testing with Jest or Mocha
Testing with Jest
Installing Jest and Related Dependencies
npm install --save-dev jest @types/jest ts-jestConfiguring Jest
Create a jest.config.js file in the project root to configure Jest.
// jest.config.js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
// Other configuration options...
};Writing Test Files
Test files are typically placed in a tests directory and end with .spec.ts. For example, to test app.controller.ts, create a app.controller.spec.ts file.
// tests/app.controller.spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import { AppController } from '../src/app.controller';
describe('AppController (e2e)', () => {
let app: INestApplication;
beforeEach(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
it('/ (GET)', () => {
return request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Hello World!');
});
});Running Tests
Add a test script to package.json:
{
"scripts": {
"test": "jest"
}
}Then run the tests:
npm run testTesting with Mocha
Installing Mocha and Related Dependencies
npm install --save-dev mocha @types/mocha ts-nodeConfiguring Mocha
Create a mocha.opts file in the project root to configure Mocha.
// mocha.opts
--require ts-node/registerWriting Test Files
Test files are typically placed in a tests directory and end with .test.ts. For example, to test app.controller.ts, create a app.controller.test.ts file.
// tests/app.controller.test.ts
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from '../src/app.module';
import { AppController } from '../src/app.controller';
describe('AppController', () => {
let app: INestApplication;
before(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
await app.init();
});
after(async () => {
await app.close();
});
it('should respond with "Hello World!"', () => {
return request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Hello World!');
});
});Running Tests
Add a test script to package.json:
{
"scripts": {
"test": "mocha -r ts-node/register tests/**/*.test.ts"
}
}Then run the tests:
npm run testNotes
- Ensure test files follow Jest or Mocha naming conventions.
- Use
beforeEachandafterEachto set up and clean up the environment for each test case. - Use
supertestto simulate HTTP requests. - To mock services or modules, use the
overrideProvidermethod ofTestingModule. - Consider using
jest.mockorsinonto mock external dependencies.
Deploying to Cloud Platforms (e.g., AWS, Google Cloud, Heroku)
Deploying to AWS
Using Elastic Beanstalk
Create an Elastic Beanstalk Application:
eb init -p node.jsCreate an Environment:
eb create my-envDeploy the Application:
eb deployUsing EC2 + Load Balancer
Create an EC2 Instance:
- Log in to the AWS Management Console and select the EC2 service.
- Create a new instance, choosing an appropriate AMI and instance type.
Configure Security Group:
- Set security group rules to allow HTTP and HTTPS traffic.
Install Node.js:
- SSH into the EC2 instance.
- Install Node.js and npm.
Upload Code:
- Use SCP or SFTP to upload the code to the EC2 instance.
Start the Application:
- Run the application on the EC2 instance.
Configure Load Balancer:
- Create a load balancer and add the EC2 instance to the target group.
Deploying to Google Cloud
Using Google Cloud Run
Create a Cloud Run Service:
- Log in to the Google Cloud Console and select the Cloud Run service.
- Create a new service and specify the Docker image.
Build the Docker Image:
- Create a Dockerfile.
- Use
gcloud builds submitto build the image.
Deploy the Service:
- Use
gcloud run deployto deploy the service.
Using Google Kubernetes Engine (GKE)
Create a Kubernetes Cluster:
- Log in to the Google Cloud Console and select the Kubernetes Engine service.
- Create a new cluster.
Create Deployment and Service:
- Write Kubernetes YAML files to define the Deployment and Service.
Deploy the Application:
- Use
kubectl apply -f <filename>.yamlto deploy the application.
Deploying to Heroku
Creating a Heroku Application
Install Heroku CLI:
npm install -g herokuLog in to Heroku:
heroku loginCreate an Application:
heroku create my-nest-appConfiguring the Application
Set the Build Environment:
heroku buildpacks:set heroku/nodejsPush Code:
git push heroku masterConfiguring Environment Variables
Set Environment Variables:
heroku config:set NODE_ENV=productionScaling the Application
Increase Dyno Count:
heroku ps:scale web=1Example
Suppose you have a NestJS project named my-nest-app. Here are the steps to deploy it to Heroku:
Initialize a Git Repository:
git init
git add .
git commit -m "Initial commit"Link the Heroku Application:
heroku create my-nest-appSet the Build Environment:
heroku buildpacks:set heroku/nodejsPush Code:
git push heroku masterSet Environment Variables:
heroku config:set NODE_ENV=productionIncrease Dyno Count:
heroku ps:scale web=1Containerizing with Docker
Creating a Dockerfile
Create a Dockerfile in the project root to define the steps for building the image.
# Use the official Node.js image as the base
FROM node:16-alpine
# Set the working directory
WORKDIR /usr/src/app
# Copy package.json and package-lock.json to the container
COPY package*.json ./
# Install dependencies
RUN npm ci
# Copy the project source code to the container
COPY . .
# Install Winston or Morgan
RUN npm install winston morgan --save
# Set environment variables
ENV NODE_ENV=production
# Expose the port
EXPOSE 3000
# Run the application
CMD ["npm", "run", "start"]Building the Docker Image
Build the Docker image with:
docker build -t my-nest-app .Running the Docker Container
Run the Docker container with:
docker run -p 3000:3000 --name my-nest-container my-nest-appLogging with Winston or Morgan
Logging with Winston
Installing Winston
Install Winston in your project:
npm install winston --saveConfiguring Winston
Create a logging configuration file, e.g., logger.js:
// logger.js
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.splat(),
winston.format.printf(info => `${info.level}: ${[info.timestamp]}: ${info.message}`)
),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
],
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple()
}));
}
module.exports = logger;Using Winston
Import and use Winston in your application:
// app.module.ts
import { Logger } from './logger';
const logger = new Logger();
logger.info('Application started.');Logging with Morgan
Installing Morgan
Install Morgan in your project:
npm install morgan --saveConfiguring Morgan
Configure Morgan in your main application file:
// main.ts
import express from 'express';
import morgan from 'morgan';
const app = express();
// Use Morgan to log requests
app.use(morgan('combined'));
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000, () => {
console.log('Listening on port 3000');
});Example
Suppose you have a NestJS project named my-nest-app. Here are the steps to containerize the application with Docker and use Winston for logging:
Create a Dockerfile:
# Dockerfile
FROM node:16-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm install winston morgan --save
ENV NODE_ENV=production
EXPOSE 3000
CMD ["npm", "run", "start"]Build the Docker Image:
docker build -t my-nest-app .Run the Docker Container:
docker run -p 3000:3000 --name my-nest-container my-nest-appConfigure Winston:
// logger.js
const winston = require('winston');
const logger = winston.createLogger({
level: 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.splat(),
winston.format.printf(info => `${info.level}: ${[info.timestamp]}: ${info.message}`)
),
transports: [
new winston.transports.Console(),
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
],
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple()
}));
}
module.exports = logger;Use Winston:
// app.module.ts
import { Logger } from './logger';
const logger = new Logger();
logger.info('Application started.');Process Management with PM2
PM2 is a powerful process management tool for managing the lifecycle of Node.js applications, including starting, restarting, stopping, and monitoring application status. Below are the steps to manage a NestJS application with PM2.
Installing PM2
Install PM2 globally using npm:
npm install pm2 -gStarting the Application
Start the NestJS application with PM2:
pm2 start npm --name "my-nest-app" -- startHere, --name "my-nest-app" specifies the application name, and -- start indicates that the npm start command should be used to start the application.
Viewing Application Status
Check the status of the application:
pm2 listThis lists all applications managed by PM2 and their statuses.
Restarting the Application
Restart the application:
pm2 restart "my-nest-app"Stopping the Application
Stop the application:
pm2 stop "my-nest-app"Deleting the Application
Delete the application:
pm2 delete "my-nest-app"Log Management
PM2 automatically manages log files for each application. View the application logs with:
pm2 logs "my-nest-app"Configuring PM2
To better manage the application, create a configuration file, e.g., ecosystem.config.js:
// ecosystem.config.js
module.exports = {
apps: [{
name: 'my-nest-app',
script: 'npm',
args: 'start',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}]
};Starting the Application with a Configuration File
Start the application using the configuration file:
pm2 start ecosystem.config.js --env productionHere, --env production specifies the use of the env_production environment variables from the configuration file.
Example
Suppose you have a NestJS project named my-nest-app. Here are the steps to manage it with PM2:
Install PM2:
npm install pm2 -gStart the Application:
pm2 start npm --name "my-nest-app" -- startView Application Status:
pm2 listRestart the Application:
pm2 restart "my-nest-app"Stop the Application:
pm2 stop "my-nest-app"Delete the Application:
pm2 delete "my-nest-app"Configure PM2:
// ecosystem.config.js
module.exports = {
apps: [{
name: 'my-nest-app',
script: 'npm',
args: 'start',
instances: 1,
autorestart: true,
watch: false,
max_memory_restart: '1G',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}]
};Start the Application with the Configuration File:
pm2 start ecosystem.config.js --env production



