ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Nest.js] simple project
    Nest.js 2021. 9. 27. 18:15

    will cover very basics of Nest.js from creating a project to Building REST API.

    Please make sure that we have installed
    1. Node - v14.17.6
    2. npm(Node Package Manager) - 7.20.3
    3. Visual Studio Code
    4. Postman (download link - https://www.postman.com/downloads/)
        or Insomnia (download link - https://insomnia.rest/download)


    STEP 1 - Install Nest.js

    1.1 check node & npm version

    $ node -v
    $ npm -v

     

    1.2 install nest.js using npm

    $ npm i -g @nestjs/cli

     


    STEP 2 - Build a basic project 

    2.1 create a nestjs project, and choose npm as package manager

    $ nest new simple // "simple" is the project name

     

    2.2 open it in VSCode

    initial structure

     

    2.3 run the application using npm

    $ npm run start

     

    2.4 check it in a browser whether it runs OK

    // if you see "Hello World!", it created properly.

     

    2.5 let's remove some files that is not used in our simple project

    and, also remove those in app.module.ts


    STEP3 - Module

    3.1 create a module, "cats"

    $ nest g module cats

    // it is automatically registered in the Root module, "app.module.ts"

    // also it created a folder, "cats", and "cats.module.ts" in its folder.


    STEP4 - Controller & Service 

    4.1 create a controller, "cats"

    $ nest g controller cats // with testing file, preferred
    or
    $ nest g controller cats --no-spec // without testing file

    // it created in folder, "cats", and automatically registered in its module, "CatsModule".

     

    4.2 create a service, "cats"

    $ nest g service cats // with testing file, preferred
    or
    $ nest g service cats --no-spec // without testing file

    // it created in folder, "cats", and NOT registered in its module, "CatsModule".

     

    4.3 register the service, "CatsService", into its module, "CatsModule"

     

    4.4 create a folder, "dto", and a dto for request payload, "cat.dto.ts"

    src/cats/dto/cat.dto.ts


    STEP 5 - Implementation

    5.1 implements "CatsService" first

    import { Injectable } from '@nestjs/common';
    import { CatDto } from './dto/cat.dto';
    
    @Injectable()
    export class CatsService {
      private readonly cats: CatDto[] = []; // 1
    
      create(catDto: CatDto) { // 2
        this.cats.push(catDto);
      }
    
      findAll(): CatDto[] { // 3
        return this.cats;
      }
    }

    // 1. use this as DB in this simple project

    // 2. catDto: CatDto -> parameter name: Type

    // 3. findall(): CatDto[] -> method name: Return Type 

     

    5.2 implement "CatsController"

    import { Body, Controller, Get, Post } from '@nestjs/common';
    import { CatsService } from './cats.service';
    import { CatDto } from './dto/cat.dto';
    
    @Controller('cats') // 1
    export class CatsController {
      constructor(private catsService: CatsService) {} // 2
    
      @Post()
      async create(@Body() catDto: CatDto) { // 3
        this.catsService.create(catDto);
      }
    
      @Get()
      async findAll(): Promise<CatDto[]> {
        return this.catsService.findAll();
      }
    }

    // 1. Route hadler entry point -> localhost:3000/cats

    // 2. Dependency Injection

    // 3. @Body() catDto: CatDto -> converts Request Payload into our CatDto


    STEP 6 - Jest

    6.1 module installation

    $ npm i --save-dev @nestjs/testing

     

    6.2 Unit testing for the service, "cats.service.ts"

    import { Test, TestingModule } from '@nestjs/testing';
    import { CatsService } from './cats.service';
    
    describe('CatsService', () => { // 1
      let service: CatsService;
    
      beforeEach(async () => {
        const module: TestingModule = await Test.createTestingModule({
          providers: [CatsService],
        }).compile();
    
        service = module.get<CatsService>(CatsService);
      });
    
      it('should be defined', () => { // 2
        expect(service).toBeDefined();
      });
    
      describe('create', () => { // 1
        it('should create a cat', () => { // 2
          const beforeCreate = service.findAll().length;
    
          service.create({
            name: 'test cat',
            age: 4,
            breed: 'unknown',
          });
    
          const afterCreate = service.findAll().length;
    
          expect(afterCreate).toBeGreaterThan(beforeCreate); // 3
        });
      });
    
      describe('finAll', () => { // 1
        it('it should return an array', () => { // 2
          const result = service.findAll();
    
          expect(result).toBeInstanceOf(Array); // 3
        });
      });
    });

    // 1. describe('XXX', () => {...}) : used for grouping several tests
          1.1 first parameter : Name of the group showing in command line
          1.2 second parameter : a callback function of the group

    // 2. it('XXX', () => {...}) : used for a test
          2.1 first parameter : Name of a test
          2.2 second parameter : test code implementation

    // 3. expect('XXX').METHOD('YYY') : making a result with developer's expectation
                                                                    by comparing 'XXX' and 'YYY' with a METHOD

     

    6.3 run the above test file. (Testing files should have a .spec or .test suffix)

    $ npm run test:cov // 1
    or
    $ npm run test:watch // 2

    // 1. find test files and show a result of where and how much and tested as "%".

    // % Stmts :  represent instructions that have been executed at least once during the unit tests.
                          For example, we have a line that contains two statements: 
    var age= 18; console.log(age) 
                          this contains a variable declaration statement and a statement that executes the log function
                          that belongs to the console object.

    // % Branch : represent if statements which conditions have been fulfilled at least once during the unit tests

    // % Funcs : represent functions that have been called at least once during the unit tests.

    // % Lines : represent code lines that have executed at least once during the unit tests.

    (added example of the % meanings)

     

    6.4 e2e testing, preferred

    - we have a e2e testing file as a defualt, in src/test/app.e2e-spec.ts

    import { Test, TestingModule } from '@nestjs/testing';
    import { INestApplication } from '@nestjs/common';
    import * as request from 'supertest';
    import { AppModule } from './../src/app.module';
    
    describe('AppController (e2e)', () => {
      let app: INestApplication;
    
      beforeEach(async () => {
        const moduleFixture: TestingModule = await Test.createTestingModule({
          imports: [AppModule],
        }).compile();
    
        app = moduleFixture.createNestApplication();
        await app.init();
      });
    
      describe('/cats', () => { 
        it('/cats (GET)', () => { 
          return request(app.getHttpServer()) // 1
            .get('/cats') // 2
            .expect(200) // 3
            .expect([]); // 3
        });
    
        it('/cats (POST)', () => {
          return request(app.getHttpServer()) // 1
          .post('/cats') // 2
          .send({ // 4
            name: 'TEST',
            age: 5,
            breed: "TEST cat"
          })
          .expect(201); // 3
        });
      });
    });

    // 1. creating a request

    // 2. HttpMethod('url')

    // 3. developer's expectation for the request

    // 4. send a request payload to server.

     

    6.5 run the e2e test file

    $ npm run test:e2e

     


    STEP 7 - API test

    7.1 run the application

    $ npm run start

     

    7.2 Using Postman or Insomnia, send a request that adding a cat

    // Request url - localhost:3000/cats
    // HTTP method - POST
    // Request payload - Body -> raw -> JSON

    // Result Status code - 201 created 

     

    7.3 send a request that reading all cats


    Additional STEP - Repository Pattern, TypeORM, MySQL

    - There is the guildline of them, please follow the link
       https://jinseo-copy-and-paste.tistory.com/11

     

    Thank you,

     

     

    'Nest.js' 카테고리의 다른 글

    [Nest.js] Life Cycle - 1 Middleware  (0) 2021.10.01
    [Nest.js] Life Cycle - advanced approach  (0) 2021.09.29
    [Nest.js] 16 - Log with Winston and WebHook  (0) 2021.09.25
    [Nest.js] 15 - Configuration  (0) 2021.09.22
    [Nest.js] 14 - Log basic  (0) 2021.09.17
Designed by Tistory.