Tu primera experiencia con Node.js

1

驴D贸nde aprender backend con Node.js actualizado?

2

Todo lo que aprender谩s sobre backend con Node.js

3

驴Qu茅 es Node.js?

4

驴Qu茅 es Node.js y para qu茅 sirve?

5

Diferencias entre Node.js y JavaScript

6

Resumen: Diferencias Nodejs y Javascript

7

Instalaci贸n de Node.js

8

Arquitectura orientada a eventos

9

Node.js para la web

Manejo y uso de Streams con Node.js

10

Introducci贸n a streams

11

Readable y Writable streams

12

Duplex y Transforms streams

Uso de utilidades de Node.js

13

Sistema operativo y sistema de archivos

14

Administrar directorios y archivos

15

Consola, utilidades y debugging

16

Clusters y procesos hijos

Crea tu primer proyecto en Express.js

17

驴Qu茅 es Express.js y para qu茅 sirve?

18

Creando tu primer servidor con Express.js

19

Request y Response Objects

Aprende a crear un API con REST

20

Anatom铆a de una API Restful

21

Estructura de una pel铆cula con Moockaru

22

Implementando un CRUD en Express.js

23

M茅todos idempotentes del CRUD

24

Implementando una capa de servicios

C贸mo conectarse con librer铆as externas en Express.js

25

Creaci贸n de una BD en MongoAtlas

26

Conexi贸n a MongoAtlas una instancia de MongoDB

27

Conexi贸n con Robot3T y MongoDB Compass a una BD

28

Implementaci贸n de las acciones de MongoDB

29

Conexi贸n de nuestros servicios con MongoDB

Conoce como funcionan los Middleware en Express.js

30

驴Qu茅 es un middleware? Capa de manejo de errores usando un middleware

31

Manejo de errores as铆ncronos y s铆ncronos en Express

32

Capa de validaci贸n de datos usando un middleware

33

驴Qu茅 es Joi y Boom?

34

Implementando Boom

35

Implementando Joi

36

Probar la validaci贸n de nuestros endpoints

37

Middlewares populares en Express.js

Implementa tests en Node.js

38

Creaci贸n de tests para nuestros endpoints

39

Creaci贸n de tests para nuestros servicios

40

Creaci贸n de tests para nuestras utilidades

41

Agregando un comando para coverage

42

Debugging e inspect

Despliega tu primera aplicaci贸n en Express.js

43

Considerando las mejores pr谩cticas para el despliegue

44

Variables de entorno, CORS y HTTPS

45

驴C贸mo implementar una capa de manejo de cach茅?

46

驴C贸mo contener tu aplicaci贸n en Docker?

47

Despliegue en Now

Conclusiones

48

驴Qu茅 aprendiste en este curso?

No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Creaci贸n de tests para nuestros endpoints

38/48
Recursos

Aportes 55

Preguntas 19

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

  • mocha: nos ayuda a correr los test
  • supertest: levanta un servidor temporal
  • sinon: crea mocks para tests
  • proxyquire inyecta los mocks cuando se requieren los paquetes

La clase no estuvo muy clara. A mi parecer falt贸 explicar con m谩s claridad lo relacionado con los test en javascript para poder entender m谩s f谩cilmente lo que se estaba estudiando.
Este profesor sabe mucho del tema pero explica demasiado r谩pido y no se alcanza a entender muchas de las cosas que habla.

Investigu茅 las documentaciones de las librer铆as para entender la clase y estos son mis apuntes por si les sirven.

Flujo de tests Mocha

<h1>Consideramos un test it(mensaje, function () {});</h1>


Si dentro del callback se lanza un error, el test se da por fallido y se pasa al siguiente test.

En caso de que la ejecuci贸n del callback termine sin errores entonces se pasa al siguiente test autom谩ticamente.

Si en la ejecuci贸n del callback llamamos a una funci贸n as铆ncrona, debemos pasarle una funci贸n 鈥榙one鈥 como par谩metro (el nombre es arbitrario).

Si pasamos ese par谩metro mocha sabr谩 que debe esperar a que la ejecutemos para pasar al siguiente test y darlo como aprobado. O en caso de que ejecutemos done(error), sabr谩 que debe pasar al siguiente pero d谩ndolo como fallido.

it(mensaje, function (done) {
	setInmediate(() => done());
});

En caso de tengamos una promesa podemos simplemente retornarla y mocha esperar谩 a que la promesa se complete, dando el test como aprobado o fallido dependiendo de si se resuelve correctamente o no.

Debemos utilizar el callback done o retornar una promesa, pero no utilizar ambos o se producir谩 un error.

it(mensaje, async function () {
	return Promise.resolve('hola');
});


Tambi茅n podemos realizar un test as铆ncrono y tratarlo como s铆ncrono con async/await. En este caso, al igual que en el caso s铆ncrono, el test depende de si la funci贸n finaliza correctamente o finaliza con un error.
鉅鉅

it(mensaje, async function () {
	const promesa = Promise.resolve('hola');

	await promesa;
});


Como no envolvemos el await en un try/catch, este lanzar谩 un error en caso de que la promesa sea rechazada, por lo tento el test pasar谩 fallido.

Testing de endpoints HTTP


Para esto utilizamos una librer铆a llamada supertest, la cual sirve para testear servidores HTTP NODE.js, nos permite env铆ar solicitudes HTTP de tipo GET, POST, PATCH, PUT, y DELETE, y recibir la respuesta.

supertest nos provee una funci贸n a la que le debemos pasar nuestra app express como par谩metro (con sus rutas establecidas), y nos retornar谩 un objeto por el cual podemos relizar solicitudes y validaciones.

const createRequester = require('supertest');
const request = createRequester(app);

request
    .get('/user')
    .expect('Content-Type', /json/)
    .expect('Content-Length', '15')
    .expect(200)
    .end(function(err, res) {
        if (err) throw err;
    });


Si estamos en un test mocha, podemos pasar el done a la funci贸n end.

request
    .get('/user')
    .expect(200)
    .end(done);


De esta manera, si hay un error mocha recibir谩 un done con el error y el test fallar谩, y si no hay error, no fallar谩 porque done no recibir谩 un error. End recibe un error first callback.

Si no usamos la funci贸n end, los expect lanzar谩n errores en el segundo par谩metro y podemos capturarlos de la siguiente manera鈥

request
    .get('/user')
    .expect(200, done);


Para leer la respuesta podemos usar un then

request
    .get('/user')
    .then(response => {
        assert(response.body.email, '[email protected]');
    });

Les recomiendo jest para los test unitarios, tanto en el front como en el back

Aprend铆 muy poco en esta clase.
.
Voy a leer los comentarios, y ver de nuevo la clase.
.
De aqu铆 salgo aprendiendo-
.
VUAAAAAAAAAAMOS

Al ejecutar el script de test me dio un error porque faltaba setear la variable NODE_ENV

鈥渢est鈥: 鈥渟et NODE_ENV=development && mocha --exit鈥

No olviden en test-server hacer uso del parse de express para formato json, el no hacerlo puede generarle error, en su defectoque la prueba falle.

const express = require('express')
const supertest = require('supertest')

function testServer(route){
    const app = express()
    app.use(express.json())
    route(app)
    return supertest(app)
}

module.exports = testServer

Algo que me di cuenta, es que es super importante que al hacer el deepEqual asegurarse que los datos que estan comparando sean exactamente iguales. En este caso tanto la data como el mensaje que se reciben.
Me estaba dando errores porque en el mensaje que retornaba de las rutas era diferente al que comparaba en el test. Me sal铆a este error:

.
As铆 que hay que estar muy pendientes con este tipo de errores.

驴Alguien sabe por qu茅 esto funciona

En 鈥榬outes/movies.js鈥

const MovieService = require('../services/MovieService')

En 鈥榯est/routes.movies.test.js鈥

const route = proxyquire('../routes/movies', {
        '../services/MovieService': MoviesServiceMock
})

Pero esto no:

En 鈥榬outes/movies.js鈥

const { MovieService } = require('../services/')

En 鈥榯est/routes.movies.test.js鈥

const route = proxyquire('../routes/movies', {
        '../services/': { MovieService: MoviesServiceMock }
})

?

Si alguno tuvo problemas con el deepEqual, es porque la funci贸n est谩 deprecada, la correcta es :


assert.deepStrictEqual(res.body, {
                    data: moviesMock,
                    message: 'movies listed',
                });

Implementar test en Node.js 馃И

Las dependencias que instalaremos solo se usar谩n en modo de desarrollo cuales son

  • mocha: nos ayuda a correr los test
  • supertest : no ayuda a levantar un sevidor temporal
  • sinon: nos ayuda a hacer mocks
  • proyquiere: nos ayuda a inyectar los mocks

El objetivo de esto es probar unicamente las rutas, no nos conectaremos a nuestros servicios como mongoDB si no que lo haremos a nuestros Mocks

Crearemos el archivo donde haremos los test

Importamos las dependencias que nos ayudar谩n

const assert = require('assert');
const proxyquire = require('proxyquire');

Importamos el creador de sevidores temporales y los mocks

const { moviesMock, MoviesServiceMock } = require('../utils/mocks/movies.js');
const testServer = require('../utils/testServer');
  • El testServer se le tiene que pasar una funcion con las rutas

Esta funcion reemplazar谩 el requiere del servicio de mongo por el de Mock que importamos

describe('routes - movies', function() {
  const route = proxyquire('../routes/movies', {
    '../services/movies': MoviesServiceMock
  });
// una vez realizado el cambio proxiquery nos 
// nos devuelve el mismo archivo pero con las 
// modificaciones, y esto lo podemos guardar 
// en una variable

Una vez el mock inyectado se lo pasamos a supertes que har谩 un servidor temporal

const request = testServer(route);

Creamos una prueba pero en vez de inyectar algo har谩 un unit test, le pasamos el nombre del test y la funci贸n a ejecutar

El done quiere fucionar铆a como un next, es decir termina aqu铆

describe('GET /movies', function() {
    it('should respond with status 200', function(done) {
      request.get('/api/movies').expect(200, done);
    });

it( una descripci贸n de lo que deberia dar, funcion a ejecutar

it('should respond with status 200', function

La funci贸n no es mas que un servidor temporal con el archivo modificado, dentro de este haremos un

routes.get(ruta a probar, expect(status esperado, done))

request.get('/api/movies').expect(200, done);

Ahora usaremos el .end que recibe una funci贸n que tiene el resultado de la petici贸n y si hay algun error,

.end((err, res) => {
        assert.deepEqual(res.body, {
          data: moviesMock,
          message: 'movies listed'
        });

usaremos assert.deepEqual(valor 1, valor 2) cual comparar谩 los datos

instalar: npm i -D mocha supertest sinon proxyquire

Tal y como todo proxy sirve para interceptar procesos, proxyquire sirve para interceptar un m贸dulo (require).

const route = proxyquire('../routes/movies', {
    '../services/movies': MoviesServiceMock,
  });

El primer par谩metro representa la ruta del archivo donde pensamos interceptar el m贸dulo (require) Ej.: 鈥樷/routes/movies鈥.

El segundo par谩metro son pares 鈥渓lave-valor鈥 en los cuales, respectivamente, cada llave representa el m贸dulo que se quiere interceptar (Ej.: 鈥樷/services/movies鈥), y cada valor representa el m贸dulo (Ej.: MoviesServiceMock) por el cual se va a reemplazar el (m贸dulo de la llave) que se est谩 interceptando.

Utilizando lo que tenemos hasta ahora quedar铆a algo como esto:

const route = proxyquire('../routes/movies', {
    '../services/movies': require('../utils/mocks/movies').MoviesServiceMock,
  });

o m谩s a fondo:

// en el archivo routes/movies.js quedar铆a algo as铆

const MoviesService = require('../services/movies');
const { MoviesServiceMock } = require('../services/mocks/movies')
const MoviesService = MoviesServiceMock;

// o sea sobrescribiendo el contenido del primer "MoviesService"

Espero no haber confundido m谩s a nadie 馃ぃ

creo que falta mas detalles sobre el tema de test, deber铆a ser un modulo completo.

Si modificaron alguna parte del c贸digo con anterioridad y ahora tienen problemas con MOCHA, este c贸digo les puede ayudar.

require('dotenv').config();

const config = {
	dev: (process.env.NODE_ENV || '').trim() !== 'production',
	port: process.env.PORT || 3000,
	cors: process.env.CORS,
	dbUser: process.env.DB_USER,
	dbPass: process.env.DB_PASSWORD,
	dbHost: process.env.DB_HOST,
	dbName: process.env.DB_NAME,
};

module.exports = {
	config,
};

he encontrado esta informacion acerca de los
tes
ya que mas adelante podrias no entender nada.

Y si encuentras mi comentario en el siguiente video, me das un corazonsito 鉂わ笍

Siempre es bueno escribir las cosas un@ mism@鈥 pero a veces es m谩s f谩cil con un simple copy/paste:

npm i -D mocha supertest sinon proxyquire

馃槂

cuando vayan a crear los 鈥榮ervicios鈥 de mock, aseg煤rense que las funciones tenga el mismo nombre que del servicio original (osea, si en su capa de servicio para obtener peliculas es getAll, en el mock coloquenlo igual), dure media hora con un error por culpa de una 鈥榮鈥 馃槂

y realmente la consola no es que ayudo mucho para solucionar el error, ya que me daba a entender que el error estaba en el archivo de test en si, y no en el mock xd

Me da el siguiente error ! 馃槩馃槩馃槶馃槶
![](

me demore pero es satisfactorio cuando entiendes y a la vez el codigo corre. ahora si a dormir ZzzZZ

Para los que quieran profundizar un poco m谩s sobre testing, les recomiendo que lean sobre Jest.

El proxyquire me genera error :
const route = proxyquire(鈥欌/controllers/routes.js鈥, {
鈥欌/services/Animals鈥 : Animals
})
TypeError: route is not a function

Si por alguna raz贸n est谩s usando Typescript en lugar de javascript como yo, este comando te resumir谩 horas de b煤squeda 馃槄

   "scripts": {
        "test": "mocha -r ts-node/register 'tests/**/*.ts'"
    },

Ayuda!!! Por fa!
Hola a todos, he intentado corregir los test para que me funcionen y no me ha sido posible:

Siendo el script de test:
鈥渢est鈥: 鈥淪ET NODE_ENV=development& mocha --exit鈥

Esto me sale en consola:





$ npm run test

[email protected] test D:\platzi-backend-node-implementando-una-capa-de-servicios\movies-api
SET NODE_ENV=development& mocha --exit

Error: No test files found: "test"
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! [email protected] test: SET NODE_ENV=development& mocha --exit
npm ERR! Exit status 1
npm ERR!
npm ERR! Failed at the [email protected] test script.
npm ERR! This is probably not a problem with npm. There is likely additional logging output above.

npm ERR! A complete log of this run can be found in:
npm ERR! C:\Users\Daniel\AppData\Roaming\npm-cache_logs\2020-07-15T14_43_35_626Z-debug.log


Realmente no veo nada adicional en el log que refiere el error del arranque.

alguien de dio este error.

npm i -D mocha supertest sinon proxyquire

Con mocha 9 se obtiene el error

Error: Not supported
    at formattedImport

Para solucionar el problema de manera temporal se debe de utilizar la versi贸n mas antigua, ejemplo 鈥渕ocha鈥: 鈥淾6.1.4鈥, con eso, el se puede continuar con la clase.

todo un gigachad hecho y derecho!

El test nos sirve para ver la calidad y futuro de nuestra app.

npm i -D mocha supertest sinon proxyquire

No entendi como se relacionan las rutas de MoviesServiceMock, cuando hacemos el test con describe, por ejemplo para seleccionar la ruta con getMovie pasando un ID

El test me ayud贸 a descubrir que mi message decia 鈥榤ovie listed鈥 en vez de 鈥榤ovies listed鈥, un error simple que tal vez nunca me hubiera dado cuenta sin el test. S煤per cool la herramienta

npm i -D mocha supertest sinon proxyquire

El video esta incompleto, hay archivos que Guillermo no explica como por ejemplo utils/mocks/mongoLib.js y otros dos archivos que estan en la carpeta de test, tampoco explica el buildMessage.js en la carpeta de utils.
Clase muy incompleta -.-

Los test no tienen en cuenta el validationSchema que hace parte de la ruta.

Excelente, no ten铆a en mente la importancia de los test de prueba y como muchos siempre los omito, pero creo que de hoy en adelante ser谩 necesario realizarlos en mi c贸digo.

proxiquire

Instalando dependencias

Creando test server para pruebas

Creando test server para pruebas

Compa帽eros ayuda!! 鈥 Me arroja 鈥淭ype: request.get is not a function鈥 del routes.movies.test.js鈥 Pero parece que soy el 煤nico 馃槮

Creo que no fue muy clara la clase, me cost贸 bastante seguirle el hilo. Aun as铆 logr茅 completarla y entender que los test son importantes pero me gustar铆a que hubiera sido mejor explicada.

A mi me daba error porque en el config/index.js en la constante config hab铆a a帽adido un .trim() al final de NODE_ENV para solucionar un problema de una clase.

Quit茅 este .trim() y anduvo bien, pero no creo que sea una soluci贸n completa.
Si a alguien le pas贸 lo mismo, lo invito a compartir su solucion!

As铆 estaba mi codigo:

const config = { 
    dev: process.env.NODE_ENV.trim() !== 'production',
    port: process.env.PORT || 3000,
    // etc
}

Me daba el siguiente TypeError:

TypeError: Cannot read property 'trim' of undefined
    at Object.<anonymous> (F:\Atom\Platzi\BackendNodeJS\moviesAPI\config\index.js:4:31)

Sacando el .trim() queda as铆:

const config = { 
    dev: process.env.NODE_ENV !== 'production',
    port: process.env.PORT || 3000,
    // etc
}

Y pasa efectivamente los test. De nuevo, si alguien tiene una mejor soluci贸n, lo invito a compartirla!

Buenas.
Alguien ha logrado hacer los test para el post, put y delete.
Me encuentro con el problema de que si intento hacer un post, el createMovie, le da igual el contenido aunque este el validator en medio, puedo hacer un post sin enviar nada, y me devuelve un 200, puedo romper cualqueir cosa que el 200 vuelve =(

Los test nos garantizan tener un c贸digo de buena calidad y si en el futuro hay cambios no se va a romper nuestro c贸digo.

Hola a todos, tengo una pregunta que quisiera pudieran aclararme, 驴Cu谩l es el sentido de hacer pruebas con mocks? al ver la este video pienso que no se esta llegando al endpoint a realizar al request, si no estamos haciendo el mockup, entonces ya se que voy a resolver, y si alguien cambia la funcionalidad del endpoint, la prueba seguir铆a pasando probablemente porque no modificaran el mock, creo que estoy confundido, pueden ayudarme a salir de esta duda?

Definitivamente hace falta un curso de testing para Node jaja me pareci贸 bastante compleja esta clase. Incluso los cursos te testing de Platzi son con Jest o Cypress entonces tenemos poca informaci贸n sobre mocha y creo que a muchos nos servir铆a un curso espec铆ficamente de 鈥渢esting para Node鈥

Si tienen este error al momento de correr el test.

Les explico porque鈥


Este fue mi error鈥

  1. En lugar de decir movies listed鈥 dec铆a **鈥楳oies Listed鈥*, esto pasa porque utiliza el m茅todo estricto, tiene que ser igual en cuanto a tipo y dato.
  2. El m茅todo que utiliza @Guillermo Rodas hoy en dia se encuentra despreciado por las nuevas versiones de node.

Entonces鈥 Hice lo siguiente

  1. Importe de manera estricta los datos
const assert = require('assert').strict;
  1. Hice unas modificaciones pertinentes para esto.
it('Should respond with the list of movies', function (done) {
			request.get('/api/movies').end((err, res) => {
				assert.deepStrictEqual(res.body, {
					data: moviesMock,
					message: 'movies listed',
				});
				done();
			});
		});
  • mocha: nos ayuda a correr los test

  • supertest: levanta un servidor temporal

  • sinon: crea mocks para tests

  • proxyquire inyecta los mocks cuando se requieren los paquetes

馃尭馃専馃尀



::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
Los Test****: Son una buena manera de poder asegurarse que nuestro codigo tiene calidad y que si en el futuro hay cambios no se vaya a romper nuestro codigo.

Hola les traigo lo que dijo el profe pero escrito

/** Verifica que tanto se parecen dos datos  */
const assert = require('assert')

/** Cada require elegimos si obtenemos el paquete real o los mocks  */
const proxyquire = require('proxyquire')

/** Mocks de la base de datos y los servicios */
const {   
  moviesMock,
  MoviesServiceMock
} = require('../utils/mocks/movies')

/** Servidor de tests */
const testServer = require('../utils/testServer')

/** describe imprime en consola y corre la funcion siguiente*/
describe('route - movies', function() {

  /** 
   * proxyquire toma el archivo del checkpoint 'routes/movies.js'
   * para probar que las peticiones esten funcionando correctamente.
   * Y para verificar que la respuesta es retornada de la manera que queremos
   * se implantan el MovieServiceMock en el lugar donde se requiere la ruta de los servicios
  */
  const route = proxyquire('../routes/movies', {

    /** intercambia services/movies por la clase MoviesServiceMock  */
    '../services/movies': MoviesServiceMock
  })

  /** Crea un servidor de prueba que maneje esta ruta declarada */
  const request = testServer(route)

  /** describe imprime en consola y llama al callback */
  describe('GET /movies', function() {

    /** 
     * Prueba: imprime este mensaje y corre el callback
     * request corre el servidor de pruebas generando una peticion get
     * que va a la ruta expuesta, y el metodo expect
     * declara esperar un status 200 y mediante done terminamos la prueba
     */
    it('should respond with status 2000', function(done) {
      request.get('/api/movies').expect(200, done)
    })

    /**
     * Prueba: hace una peticion get a la ruta y verifica el contenido
     * request.get accede a la ruta, .end maneja la respuesta y el error
     * pero solamente vamos a evaluar la respuesta,
     * asset es un modulo core de node que nos permite evaluar el tipo y contenido de valores y variables
     * en este caso verificamos res.body sea estrictamente igual a lo que enviamos como segundo parametro
     * y finaliza la prueba con done
     */
    it('should respond with the list of movies', function(done) {
      request.get('/api/movies').end((err, res) => {
        assert.deepEqual(res.body, {
          data: moviesMock,
          message: 'movies listed'
        })
        done()
      })
    })
  })
})

si proxyquire retorna un objeto, se tiene un error de tipo

TypeError: route is not a function

por lo que me toco sacar la funcion que espera testServer de esta forma, no creo sea la mejor pero me sirvi贸

const {moviesApi: route} = proxyquire('../routes/movies.js', {
    '../services/movies': MoviesServiceMock
  });

espero les sirva

El t茅rmino 鈥榤ocha鈥 no se reconoce como nombre de un cmdlet, funci贸n, archivo de script o programa ejecutable.

Alguien le ha salido ese error? he comprobado que si tengo instalado el mocha y tmb lo tengo en el package.json