Un curso de pruebas unitarias para Nest estaría increíble! 🤩.
Sería un PLUS para aprender todas las bases 😎.
Introducción
¿Ya terminaste el Curso de NestJS: Programación Modular?
Platzi Store: presentación del proyecto e instalación
Database
Cómo instalar Docker para este proyecto
Configuración de PostgresSQL en Docker
Explorando postgres con interfaces gráficas y terminal
Integración de node-postgres con NestJS
Conexión como inyectable y ejecutando un SELECT
Usando variables de ambiente
TypeORM
¿Qué es un ORM? Instalando y configurando TypeORM Module
Creando tu primera entidad
TypeORM: active record vs. repositories
Crear, actualizar y eliminar
Cambiar a Mysql demo (opcional)
Migraciones
Sync Mode vs. Migraciones en TypeORM
Configurando migraciones y npm scripts
Corriendo migraciones
Modificando una entidad
Relaciones
Relaciones uno a uno
Resolviendo la relación uno a uno en el controlador
Relaciones uno a muchos
Resolviendo la relación uno a muchos en el controlador
Relaciones muchos a muchos
Resolviendo la relación muchos a muchos en el controlador
Manipulación de arreglos en relaciones muchos a muchos
Relaciones muchos a muchos personalizadas
Resolviendo la relación muchos a muchos personalizada en el controlador
Consultas
Paginación
Filtrando precios con operadores
Agregando indexadores
Modificando el naming
Serializar
Próximos pasos
Cómo solucionar una referencia circular entre módulos
Continúa con el Curso de NestJS: Autenticación con Passport y JWT
No tienes acceso a esta clase
¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera
Aportes 9
Preguntas 2
Un curso de pruebas unitarias para Nest estaría increíble! 🤩.
Sería un PLUS para aprender todas las bases 😎.
Yo sí que quiero un curso de pruebas unitarias en Nest
Un curso de TDD (Test Driven Development) con NestJS estaría genial.
nest g s users/services/orders --flat
nest g co users/controllers/orders --flat
nest g co users/services/order-item --flat
nest g co users/controllers/order-item --flat
// src\users\dtos\order.dto.ts
import { ApiProperty, PartialType } from "@nestjs/swagger";
import { IsNotEmpty, IsPositive } from "class-validator";
export class CreateOrderDto {
@IsPositive()
@IsNotEmpty()
@ApiProperty()
readonly customerId: number;
}
export class UpdateOrderDto extends PartialType(CreateOrderDto){}
// src\users\services\orders.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { CreateOrderDto, UpdateOrderDto } from '../dtos/order.dto';
import { Customer } from '../entities/customer.entity';
import { Order } from '../entities/order.entity';
@Injectable()
export class OrdersService {
constructor(
@InjectRepository(Order) private orderRepo:Repository<Order>,
@InjectRepository(Customer) private customerRepo:Repository<Customer>
){}
findAll(){
return this.orderRepo.find();
}
async findOne(id: number){
const order = await this.orderRepo.findOne(id);
if(!order) {
throw new NotFoundException(`order ${id} not found`);
}
return order;
}
async create(data: CreateOrderDto){
const order = new Order();
if (data.customerId) {
const customer = await this.customerRepo.findOne(data.customerId);
order.customer = customer;
}
return this.orderRepo.save(order);
}
async update(id:number, changes:UpdateOrderDto){
const order = await this.orderRepo.findOne(id);
if (changes.customerId) {
const customer = await this.customerRepo.findOne(changes.customerId);
order.customer = customer;
}
return this.orderRepo.save(order);
}
delete(id:number){
return this.orderRepo.delete(id);
}
}
// src\users\controllers\orders.controller.ts
import { Body, Controller, Delete, Get, Param, ParseIntPipe, Post, Put } from '@nestjs/common';
import { CreateOrderDto, UpdateOrderDto } from '../dtos/order.dto';
import { OrdersService } from '../services/orders.service';
@Controller('orders')
export class OrdersController {
constructor(private ordersService: OrdersService){}
@Get('')
findAll(){
return this.ordersService.findAll();
}
@Get(':id')
findOne(
@Param('id', ParseIntPipe) id: number
){
return this.ordersService.findOne(id);
}
@Post('')
create(@Body() payload: CreateOrderDto){
return this.ordersService.create(payload);
}
@Put(':id')
update(
@Param('id', ParseIntPipe) id:number,
@Body() payload: UpdateOrderDto
){
return this.ordersService.update(id, payload);
}
@Delete(':id')
delete(@Param('id') id: number){
return this.ordersService.delete(id);
}
}
// src\users\dtos\order-item.dto.ts
import { ApiProperty, PartialType } from "@nestjs/swagger";
import { IsNotEmpty, IsNumber, IsPositive } from "class-validator";
export class CreateOrderItemDto {
@IsNumber()
@IsPositive()
@IsNotEmpty()
@ApiProperty()
readonly orderId: number;
@IsNumber()
@IsPositive()
@IsNotEmpty()
@ApiProperty()
readonly productId: number;
@IsNumber()
@IsPositive()
@IsNotEmpty()
@ApiProperty()
readonly quantity: number;
}
export class UpdateOrderItemDto extends PartialType(CreateOrderItemDto){}
// src\products\products.module.ts
@Module({
...
exports: [..., TypeOrmModule], // export TypeOrmModule
})
export class ProductsModule {}
// src\users\services\order-item.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Product } from 'src/products/entities/product.entity';
import { Repository } from 'typeorm';
import { CreateOrderItemDto, UpdateOrderItemDto } from '../dtos/order-item.dto';
import { OrderItem } from '../entities/order-item.entity';
import { Order } from '../entities/order.entity';
@Injectable()
export class OrderItemService {
constructor(
@InjectRepository(Product) private productRepo:Repository<Product>,
@InjectRepository(Order) private orderRepo:Repository<Order>,
@InjectRepository(OrderItem) private orderItemRepo: Repository<OrderItem>
){}
async create(data: CreateOrderItemDto){
const order = await this.orderRepo.findOne(data.orderId);
const product = await this.productRepo.findOne(data.productId);
const newOrderItem = new OrderItem();
newOrderItem.order = order;
newOrderItem.product = product;
newOrderItem.quantity = data.quantity;
return this.orderItemRepo.save(newOrderItem)
}
}
// src\users\controllers\order-item.controller.ts
import { Body, Controller, Post } from '@nestjs/common';
import { CreateOrderItemDto } from '../dtos/order-item.dto';
import { OrderItemService } from '../services/order-item.service';
@Controller('order-item')
export class OrderItemController {
constructor(private orderItemService: OrderItemService){}
@Post('')
create(@Body() payload: CreateOrderItemDto){
return this.orderItemService.create(payload);
}
}
// src\users\services\orders.service.ts
async findOne(id: number){
const order = await this.orderRepo.findOne(id, {
relations: ["items", "items.product"] // Agregamos relacion
});
if(!order) {
throw new NotFoundException(`order ${id} not found`);
}
return order;
}
Cuando usan el comando generate del CLI pueden pasarle el argumento --no-spec
para que no cree los archivos para pruebas unitarias
// src\users\services\order-item.service.ts
findAll(){
return this.orderItemRepo.find({
relations: ['order', 'order.customer']
});
}
findOne(id: number){
return this.orderItemRepo.findOne(id,{
relations: ['order', 'product']
});
}
async update(id: number, changes: UpdateOrderItemDto){
const orderItem = await this.orderItemRepo.findOne(id);
if (changes.orderId) {
const order = await this.orderRepo.findOne(changes.orderId);
orderItem.order = order;
}
if (changes.productId) {
const product = await this.productRepo.findOne(changes.productId);
orderItem.product = product;
}
if(changes.quantity){
orderItem.quantity = changes.quantity;
}
return this.orderItemRepo.save(orderItem);
}
delete(id: number){
return this.orderItemRepo.delete(id);
}
// src\users\controllers\order-item.controller.ts
@Get('')
findAll(){
return this.orderItemService.findAll();
}
@Get(':id')
findOne(@Param('id', ParseIntPipe) id: number){
return this.orderItemService.findOne(id);
}
@Put(':id')
update(
@Param('id', ParseIntPipe) id: number,
@Body() payload: UpdateOrderItemDto
){
return this.orderItemService.update(id, payload);
}
@Delete(':id')
delete(@Param('id') id: number){
return this.orderItemService.delete(id);
}
Un curso de prueba unitarias en Nest js Por favor
Otro tip, pueden usar nest generate resource <nombre-del-recurso>
para autogenerar un CRUD (link):
$ nest g resource users
> ? What transport layer do you use? GraphQL (code first)
> ? Would you like to generate CRUD entry points? Yes
> CREATE src/users/users.module.ts (224 bytes)
> CREATE src/users/users.resolver.spec.ts (525 bytes)
> CREATE src/users/users.resolver.ts (1109 bytes)
> CREATE src/users/users.service.spec.ts (453 bytes)
> CREATE src/users/users.service.ts (625 bytes)
> CREATE src/users/dto/create-user.input.ts (195 bytes)
> CREATE src/users/dto/update-user.input.ts (281 bytes)
> CREATE src/users/entities/user.entity.ts (187 bytes)
> UPDATE src/app.module.ts (312 bytes)
Esta super bien la clase, pero como sujerencia estas deben ser mas cortas. Lo ideal es que duren un maximo de 10 minutos porque de lo contrario es mayor el esfuerzo mental que un alumno debe hacer y facilmente pierda el hilo del tema.
Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Regístrate o inicia sesión para participar.