🤞 NomadcoderでNestjsの練習をする
71461 ワード
レッスンリンクはこちらをクリックしてください👆
🧑 Nestjsを学ぶ
👳‐‐‐‐‐‐‐‐‐Jestやってみる
👱」フォルダ構造
👮♂️ 合成コード // main.ts
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}),
);
await app.listen(3000);
}
bootstrap();
// app.module.ts
import { Module } from '@nestjs/common';
import { MoviesModule } from './movies/movies.module';
import { AppController } from './app.controller';
@Module({
imports: [MoviesModule],
controllers: [AppController],
providers: [],
})
export class AppModule {}
//app.controller.js
import { Controller, Get } from '@nestjs/common';
@Controller('')
export class AppController {
@Get()
home() {
return 'Welcome to my Movie API';
}
}
//movies.modules.ts
import { Module } from '@nestjs/common';
import { MoviesController } from './movies.controller';
import { MoviesService } from './movies.service';
@Module({
controllers: [MoviesController],
providers: [MoviesService],
})
export class MoviesModule {}
//movies.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { CreateMovieDto } from './dto/create-movie.dto';
import { UpdateMovieDto } from './dto/update-movie.dto';
import { Movie } from './entities/movie.entity';
@Injectable()
export class MoviesService {
private movies: Movie[] = [];
getAll(): Movie[] {
return this.movies;
}
getOne(id: number): Movie {
const movie = this.movies.find((movie) => movie.id === id);
if (!movie) {
throw new NotFoundException(`Movie with ID ${id} not found.`);
}
return movie;
}
deleteOne(id: number) {
this.getOne(id);
this.movies = this.movies.filter((movie) => movie.id !== id);
}
create(movieData: CreateMovieDto) {
this.movies.push({
id: this.movies.length + 1,
...movieData,
});
}
update(id: number, updateData: UpdateMovieDto) {
const movie = this.getOne(id);
this.deleteOne(id);
this.movies.push({ ...movie, ...updateData });
}
}
//movies.controller.ts
import {
Body,
Controller,
Delete,
Get,
Param,
Patch,
Post,
} from '@nestjs/common';
import { CreateMovieDto } from './dto/create-movie.dto';
import { UpdateMovieDto } from './dto/update-movie.dto';
import { Movie } from './entities/movie.entity';
import { MoviesService } from './movies.service';
@Controller('movies')
export class MoviesController {
constructor(private readonly moviesService: MoviesService) {}
@Get()
getAll(): Movie[] {
return this.moviesService.getAll();
}
@Get('/:id')
getOne(@Param('id') movieId: number): Movie {
return this.moviesService.getOne(movieId);
}
@Post()
create(@Body() movieData: CreateMovieDto) {
return this.moviesService.create(movieData);
}
@Delete('/:id')
delete(@Param('id') movieId: number) {
return this.moviesService.deleteOne(movieId);
}
@Patch('/:id')
update(@Param('id') movieId: number, @Body() updateData: UpdateMovieDto) {
return this.moviesService.update(movieId, updateData);
}
}
//movie.entity.ts
export class Movie {
id: number;
title: string;
year: number;
genres: string[];
}
//create-movie.dto.ts
import { IsNumber, IsString, IsOptional } from 'class-validator';
export class CreateMovieDto {
@IsString()
readonly title: string;
@IsNumber()
readonly year: number;
@IsOptional()
@IsString({ each: true })
readonly genres: string[];
}
//update-movie.dto.ts
import { PartialType } from '@nestjs/mapped-types';
import { CreateMovieDto } from './create-movie.dto';
export class UpdateMovieDto extends PartialType(CreateMovieDto) {}
//movies.service.spec.ts
import { NotFoundException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { MoviesService } from './movies.service';
describe('MoviesService', () => {
let service: MoviesService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MoviesService],
}).compile();
service = module.get<MoviesService>(MoviesService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
describe('getAll', () => {
it('should return an array', () => {
const result = service.getAll();
expect(result).toBeInstanceOf(Array);
});
});
describe('getOne', () => {
it('should return a movie', () => {
service.create({
title: 'Test Movie',
genres: ['test'],
year: 2000,
});
const movie = service.getOne(1);
expect(movie).toBeDefined();
expect(movie.id).toEqual(1);
});
it('should throw 404 error', () => {
try {
service.getOne(999);
} catch (e) {
expect(e).toBeInstanceOf(NotFoundException);
expect(e.message).toEqual(`Movie with ID 999 not found.`);
}
});
});
describe('deleteOne', () => {
it('deletes a movie', () => {
service.create({
title: 'Test Movie',
genres: ['Test'],
year: 2000,
});
const allMovies = service.getAll();
service.deleteOne(1);
const afterDelete = service.getAll();
expect(afterDelete.length).toEqual(allMovies.length - 1);
});
it('should return a 404', () => {
try {
service.deleteOne(999);
} catch (e) {
expect(e).toBeInstanceOf(NotFoundException);
expect(e.message).toEqual(`Movie with ID 999 not found.`);
}
});
});
describe('create', () => {
it('should create a movie', () => {
const beforeCreate = service.getAll().length;
service.create({
title: 'Test Movie',
genres: ['Test'],
year: 2000,
});
const afterCreate = service.getAll().length;
expect(afterCreate).toEqual(beforeCreate + 1);
});
});
describe('dupdate', () => {
it('should update a movie', () => {
service.create({
title: 'Test Movie',
genres: ['Test'],
year: 2000,
});
service.update(1, { title: 'Updated Test' });
const movie = service.getOne(1);
expect(movie.title).toEqual('Updated Test');
});
it('should throw a NotFoundExe', () => {
try {
service.update(999, {});
} catch (e) {
expect(e).toBeInstanceOf(NotFoundException);
expect(e.message).toEqual(`Movie with ID 999 not found.`);
}
});
});
});
//app.e2e-spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication, ValidationPipe } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';
describe('AppController (e2e)', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}),
);
await app.init();
});
it('/ (GET)', () => {
return request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Welcome to my Movie API');
});
describe('/movies', () => {
it('GET', () => {
return request(app.getHttpServer()).get('/movies').expect(200).expect([]);
});
it('POST 201', () => {
return request(app.getHttpServer())
.post('/movies')
.send({
title: 'Test',
year: 2000,
genres: ['test'],
})
.expect(201);
});
it('POST 400', () => {
return request(app.getHttpServer())
.post('/movies')
.send({
title: 'Test',
year: 2000,
genres: ['test'],
other: 'thing',
})
.expect(400);
});
it('DELETE', () => {
return request(app.getHttpServer()).delete('/movies').expect(404);
});
});
describe('/movies/:id', () => {
it('GET 200', () => {
return request(app.getHttpServer()).get('/movies/1').expect(200);
});
it('GET 404', () => {
return request(app.getHttpServer()).get('/movies/999').expect(404);
});
it('PATCH 200', () => {
return request(app.getHttpServer())
.patch('/movies/1')
.send({ title: 'Updated Test' })
.expect(200);
});
it('DELETE 200', () => {
return request(app.getHttpServer()).delete('/movies/1').expect(200);
});
});
});
Reference
この問題について(🤞 NomadcoderでNestjsの練習をする), 我々は、より多くの情報をここで見つけました
https://velog.io/@devgosunman/Nestjs-연습-with-Nomadcoder
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
// main.ts
import { ValidationPipe } from '@nestjs/common';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}),
);
await app.listen(3000);
}
bootstrap();
// app.module.ts
import { Module } from '@nestjs/common';
import { MoviesModule } from './movies/movies.module';
import { AppController } from './app.controller';
@Module({
imports: [MoviesModule],
controllers: [AppController],
providers: [],
})
export class AppModule {}
//app.controller.js
import { Controller, Get } from '@nestjs/common';
@Controller('')
export class AppController {
@Get()
home() {
return 'Welcome to my Movie API';
}
}
//movies.modules.ts
import { Module } from '@nestjs/common';
import { MoviesController } from './movies.controller';
import { MoviesService } from './movies.service';
@Module({
controllers: [MoviesController],
providers: [MoviesService],
})
export class MoviesModule {}
//movies.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { CreateMovieDto } from './dto/create-movie.dto';
import { UpdateMovieDto } from './dto/update-movie.dto';
import { Movie } from './entities/movie.entity';
@Injectable()
export class MoviesService {
private movies: Movie[] = [];
getAll(): Movie[] {
return this.movies;
}
getOne(id: number): Movie {
const movie = this.movies.find((movie) => movie.id === id);
if (!movie) {
throw new NotFoundException(`Movie with ID ${id} not found.`);
}
return movie;
}
deleteOne(id: number) {
this.getOne(id);
this.movies = this.movies.filter((movie) => movie.id !== id);
}
create(movieData: CreateMovieDto) {
this.movies.push({
id: this.movies.length + 1,
...movieData,
});
}
update(id: number, updateData: UpdateMovieDto) {
const movie = this.getOne(id);
this.deleteOne(id);
this.movies.push({ ...movie, ...updateData });
}
}
//movies.controller.ts
import {
Body,
Controller,
Delete,
Get,
Param,
Patch,
Post,
} from '@nestjs/common';
import { CreateMovieDto } from './dto/create-movie.dto';
import { UpdateMovieDto } from './dto/update-movie.dto';
import { Movie } from './entities/movie.entity';
import { MoviesService } from './movies.service';
@Controller('movies')
export class MoviesController {
constructor(private readonly moviesService: MoviesService) {}
@Get()
getAll(): Movie[] {
return this.moviesService.getAll();
}
@Get('/:id')
getOne(@Param('id') movieId: number): Movie {
return this.moviesService.getOne(movieId);
}
@Post()
create(@Body() movieData: CreateMovieDto) {
return this.moviesService.create(movieData);
}
@Delete('/:id')
delete(@Param('id') movieId: number) {
return this.moviesService.deleteOne(movieId);
}
@Patch('/:id')
update(@Param('id') movieId: number, @Body() updateData: UpdateMovieDto) {
return this.moviesService.update(movieId, updateData);
}
}
//movie.entity.ts
export class Movie {
id: number;
title: string;
year: number;
genres: string[];
}
//create-movie.dto.ts
import { IsNumber, IsString, IsOptional } from 'class-validator';
export class CreateMovieDto {
@IsString()
readonly title: string;
@IsNumber()
readonly year: number;
@IsOptional()
@IsString({ each: true })
readonly genres: string[];
}
//update-movie.dto.ts
import { PartialType } from '@nestjs/mapped-types';
import { CreateMovieDto } from './create-movie.dto';
export class UpdateMovieDto extends PartialType(CreateMovieDto) {}
//movies.service.spec.ts
import { NotFoundException } from '@nestjs/common';
import { Test, TestingModule } from '@nestjs/testing';
import { MoviesService } from './movies.service';
describe('MoviesService', () => {
let service: MoviesService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MoviesService],
}).compile();
service = module.get<MoviesService>(MoviesService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
describe('getAll', () => {
it('should return an array', () => {
const result = service.getAll();
expect(result).toBeInstanceOf(Array);
});
});
describe('getOne', () => {
it('should return a movie', () => {
service.create({
title: 'Test Movie',
genres: ['test'],
year: 2000,
});
const movie = service.getOne(1);
expect(movie).toBeDefined();
expect(movie.id).toEqual(1);
});
it('should throw 404 error', () => {
try {
service.getOne(999);
} catch (e) {
expect(e).toBeInstanceOf(NotFoundException);
expect(e.message).toEqual(`Movie with ID 999 not found.`);
}
});
});
describe('deleteOne', () => {
it('deletes a movie', () => {
service.create({
title: 'Test Movie',
genres: ['Test'],
year: 2000,
});
const allMovies = service.getAll();
service.deleteOne(1);
const afterDelete = service.getAll();
expect(afterDelete.length).toEqual(allMovies.length - 1);
});
it('should return a 404', () => {
try {
service.deleteOne(999);
} catch (e) {
expect(e).toBeInstanceOf(NotFoundException);
expect(e.message).toEqual(`Movie with ID 999 not found.`);
}
});
});
describe('create', () => {
it('should create a movie', () => {
const beforeCreate = service.getAll().length;
service.create({
title: 'Test Movie',
genres: ['Test'],
year: 2000,
});
const afterCreate = service.getAll().length;
expect(afterCreate).toEqual(beforeCreate + 1);
});
});
describe('dupdate', () => {
it('should update a movie', () => {
service.create({
title: 'Test Movie',
genres: ['Test'],
year: 2000,
});
service.update(1, { title: 'Updated Test' });
const movie = service.getOne(1);
expect(movie.title).toEqual('Updated Test');
});
it('should throw a NotFoundExe', () => {
try {
service.update(999, {});
} catch (e) {
expect(e).toBeInstanceOf(NotFoundException);
expect(e.message).toEqual(`Movie with ID 999 not found.`);
}
});
});
});
//app.e2e-spec.ts
import { Test, TestingModule } from '@nestjs/testing';
import { INestApplication, ValidationPipe } from '@nestjs/common';
import * as request from 'supertest';
import { AppModule } from './../src/app.module';
describe('AppController (e2e)', () => {
let app: INestApplication;
beforeAll(async () => {
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule],
}).compile();
app = moduleFixture.createNestApplication();
app.useGlobalPipes(
new ValidationPipe({
whitelist: true,
forbidNonWhitelisted: true,
transform: true,
}),
);
await app.init();
});
it('/ (GET)', () => {
return request(app.getHttpServer())
.get('/')
.expect(200)
.expect('Welcome to my Movie API');
});
describe('/movies', () => {
it('GET', () => {
return request(app.getHttpServer()).get('/movies').expect(200).expect([]);
});
it('POST 201', () => {
return request(app.getHttpServer())
.post('/movies')
.send({
title: 'Test',
year: 2000,
genres: ['test'],
})
.expect(201);
});
it('POST 400', () => {
return request(app.getHttpServer())
.post('/movies')
.send({
title: 'Test',
year: 2000,
genres: ['test'],
other: 'thing',
})
.expect(400);
});
it('DELETE', () => {
return request(app.getHttpServer()).delete('/movies').expect(404);
});
});
describe('/movies/:id', () => {
it('GET 200', () => {
return request(app.getHttpServer()).get('/movies/1').expect(200);
});
it('GET 404', () => {
return request(app.getHttpServer()).get('/movies/999').expect(404);
});
it('PATCH 200', () => {
return request(app.getHttpServer())
.patch('/movies/1')
.send({ title: 'Updated Test' })
.expect(200);
});
it('DELETE 200', () => {
return request(app.getHttpServer()).delete('/movies/1').expect(200);
});
});
});
Reference
この問題について(🤞 NomadcoderでNestjsの練習をする), 我々は、より多くの情報をここで見つけました https://velog.io/@devgosunman/Nestjs-연습-with-Nomadcoderテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol