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 servicios

39/48
Recursos

Aportes 43

Preguntas 4

Ordenar por:

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

Creo que investigar茅 m谩s porque entend铆 un 50% 馃く馃く

隆ESTO ES INCEIBLEMENTE CONFUSO!!!
El profesor va muy muy r谩pido y no entiendo 馃槓馃槬馃槪

![](

驴Que es un stub?

Personalmente ya he realizado muchos tests en React y JS, y al ver este curso not茅 que no haber tenido ese background, habr铆a entendido muy poco.
Hace falta dentro de la ruta un curso dedicado a tests para que al llegar a este punto se pueda entender con naturalidad todo lo que dice porque s铆, se asumen conceptos, ideas, y hasta c贸digo, pues quedan en el aire los conceptos de describe, e it por citar un par de ejemplos.

la verdad entend铆 que los test, es para identificar que todo este bien escrito o funcionando como deber铆a ser desde un inicio.

pero de ah铆 a los c贸digos, ni la menor idea de lo que trata鈥
por lo cual 鈥 ir茅 a investigar o si alguien me puede explicar seria lo mejor.

Cuando usamos

Nuestro archivo de pruebas queda modificado solo para las pruebas, quedando as铆.

Al correr nuestro primer test

hace una petici贸n a moviesServices.getMovies({}), el cual ya se encuentra modificado con el mock, que le pasamos en el proxyquery.

por lo que el archivo estar铆a temporalmente modificado para pruebas a esta forma.

Recordemos que MongoLibMock , remplaza el metodo getAll, por lo que regresa un stub de sinon, para simular una respuesta de una consulta al endpoint.

Regresando al test,鈥 este compara getAllStub.called con true, para comprobar si fue llamado.
getAllStub se encuentra en el mock de mongoLib, y es el mismo stub ocupado en el archivo modificado temporalmente de movies.js y en el de pruebas, por eso la funci贸n called puede ser utilizada.


Para el segundo test, se compara el mock de pruebas con el que nos regresar铆a la petici贸n a getMovies({})

Es el mismo archivo, por lo que el test pasa.

Aunque siempre debemos seguir alimentando nuestro conocimiento por nuestra propia cuenta, seria bueno que profundicen mas en 驴el por qu茅? de las cosas.

Listo, aunque tengo que repasar.

Los tests siempre han sido mi dolor de cabez :S 隆Necesito profundizar m谩s en test!

Esta lectura esta interesante para entender un poco mas acerca de tests y los terminos nombrados https://solidgeargroup.com/tests-unitarios-en-javascript-sinon/?lang=es

Proxyquire reemplaza los requires originales por los Mock que creamos

He estado horas revisando el codigo pero no puedo hacerlo funcionar, el error que obtengo es TypeError: MoviesService is not a constructor, cuando llamo a const moviesService = new MoviesServices(); alguien me puede ayudar?

Este es mi codigo para services.movies.test.js

const assert = require('assert');
const proxyquire = require('proxyquire');
const { MongoLibMock, getAllStub } = require('../utils/mocks/mongoLib');

const { moviesMock } = require('../utils/mocks/movies');


describe('services - movies', function(){
    const MoviesServices = proxyquire('../services/movies', {'../lib/mongo': MongoLibMock});
    const moviesService = new MoviesServices();

    describe('when getMovies method is called', async function(){
        it('should call the getall MongoLib method', async function(){
            await moviesService.getMovies({});
            assert.strictEqual(getAllStub.called, true);
        })
    })
})

Y este es mi services/movies.js

`const MongoLib = require(鈥欌/lib/mongo鈥);
class MoviesService{
constructor() {
this.collection = 鈥榤ovies鈥;
this.mongoDB = new MongoLib();
}

async getMovies({tags}){
    const query = tags && { tags: { $in: tags} };
    const movies = await this.mongoDB.getAll(this.collection, query);
    return movies || [];
}

async getMovie({ movieId }){
    const movie = await this.mongoDB.get(this.collection, movieId);
    return movie || {};
}

async createMovie({ movie }){
    const createdMovieId = await this.mongoDB.create(this.collection, movie);
    return createdMovieId;
}

async updateMovie({ movieId, movie}){
    const updatedMovieId = await this.mongoDB.update(this.collection, movieId, movie);
    return updatedMovieId;
}

async deleteMovie({ movieId }){
    const deletedMovieId = await this.mongoDB.delete(this.collection, movieId)
    return deletedMovieId;
}

}

module.exports = MoviesService;`

deepEqual() esta deprecado ahora es recomendado deepStrictEqual()

El test falla y no encuentro la raz贸n

  routes - movies
    GET /movies
      鈭 should respond with status 200  (50ms)
      鈭 should respond with the list of movies 

  service - movies
    when getMovies method is called
      鈭 should call the getAll Mongolib method
      1) should return an array of movies


  3 passing (214ms)
  1 failing

El deepEqual esta obleto

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

const { MongoLibMock, getAllStub} = require('../utils/mocks/mongoLib');

const { moviesMock } = require("../utils/mocks/movies");

describe("service - movies", function(){
    const MoviesServices = proxyquire('../services/movies', {
        '../lib/mongo': MongoLibMock
    });

    const moviesService = new MoviesServices();

    describe("when getMovies method is called", async function(){
        it('should call the getAll Mongolib method', async function(){
            await moviesService.getMovies({});
            assert.strictEqual(getAllStub.called, true);
        });
        it('should return an array of movies', async function(){
            const result = await moviesService.getMovies({});
            const expected = moviesMock;
            assert.deepEqual(result, expected, "cual sera el error");
        });
    });

});

me arroja el siguiente error. Alguna Idea!

ya he comparado mi c贸digo con el del profesor y todo esta bien


> backend-con-nodejs@1.0.0 test /Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api
> mocha --exit


ProxyquireError: Invalid stub: "../services/movies" cannot be undefined
    at Proxyquire.load (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/proxyquire/lib/proxyquire.js:115:13)
    at Suite.<anonymous> (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/test/routes.movies.test.js:8:17)
    at Object.create (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/mocha/lib/interfaces/common.js:140:19)
    at context.describe.context.context (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/mocha/lib/interfaces/bdd.js:42:27)
    at Object.<anonymous> (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/test/routes.movies.test.js:7:1)
    at Module._compile (internal/modules/cjs/loader.js:956:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
    at Module.load (internal/modules/cjs/loader.js:812:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Module.require (internal/modules/cjs/loader.js:849:19)
    at require (internal/modules/cjs/helpers.js:74:18)
    at requireOrImport (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/mocha/lib/esm-utils.js:15:12)
    at Object.exports.loadFilesAsync (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/mocha/lib/esm-utils.js:28:26)
    at Mocha.loadFilesAsync (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/mocha/lib/mocha.js:351:19)
    at singleRun (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/mocha/lib/cli/run-helpers.js:107:15)
    at exports.runMocha (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/mocha/lib/cli/run-helpers.js:144:11)
    at Object.exports.handler (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/mocha/lib/cli/run.js:306:11)
    at Object.runCommand (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/yargs/lib/command.js:242:26)
    at Object.parseArgs [as _parseArgs] (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/yargs/yargs.js:1113:24)
    at Object.parse (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/yargs/yargs.js:575:25)
    at Object.exports.main (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/mocha/lib/cli/cli.js:68:6)
    at Object.<anonymous> (/Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api/node_modules/mocha/bin/mocha:133:29)
    at Module._compile (internal/modules/cjs/loader.js:956:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:973:10)
    at Module.load (internal/modules/cjs/loader.js:812:32)
    at Function.Module._load (internal/modules/cjs/loader.js:724:14)
    at Function.Module.runMain (internal/modules/cjs/loader.js:1025:10)
    at internal/main/run_main_module.js:17:11
npm ERR! code ELIFECYCLE
npm ERR! errno 1
npm ERR! backend-con-nodejs@1.0.0 test: `mocha --exit`
npm ERR! Exit status 1
npm ERR! 
npm ERR! Failed at the backend-con-nodejs@1.0.0 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!     /Users/carlosramirez/.npm/_logs/2020-04-04T09_39_12_923Z-debug.log

carlosramirez@MacBook-Pro-de-Carlos /Applications/XAMPP/xamppfiles/htdocs/platzi master/backend-con-nodejs/movies-api                                                                                           master
鈿 ```

Me confund铆 un poco, pero pues seguir con toda y miarar la documentaci贸n y explicaciones de los compa帽eros鈥 馃尭馃尀馃槏


:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

::::::::::::::::::::::::::::::::::::::::::::.::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

Si no estan familiarizados con el describe
o el it, les recomiendo el curso de testing con jasmine. (exclusivamente en la seccion con Node.js).

Ah铆 van a poder entender mejor su uso. Tiene una sintaxis muy similar a la de mocha para los tests.

B谩sicamente el describe el como un agrupador de las pruebas y el it es el core del test, en donde se especifica lo que el server debe retornar.

El MongoLibMock reemplaza el uso Mongo, y MoviesServices (con ayuda de proxyquire) simula el comportamiento de la capa de servicio MoviesService

NO HAY QUE RENDIRSE ni desmotivarse si no se comprende todo, es cuesti贸n de investigar un poco.

Pueden entender m谩s sobre 鈥渟tubs鈥 en este video

Terrible, hay muchas cosas que se pasan por alto y eso que voy con toda la escuela de JavaScript. Empez贸 muy bien el curso pero estas ultimas clases est谩n muy flojas.

Explicacion del archivo de test creado en esta clase

/** Modulo core que compara variables, valores y objetos de manera estricta */
const assert = require('assert')

/** Modulo de inyeccion de datos / cambia la ruta del require en cualquier modulo */
const proxyquire = require('proxyquire')

/** 
 * Mock de la libreria de mongo y de sus metodos
 * / clase de los metodos de la libreria y detector de peticionees a los metodos
 * */
const { 
  MongoLibMock, 
  getAllStub 
} = require('../utils/mocks/mongoLib')

/** Mock de la DB / lista de peliculas */
const { moviesMock } = require('../utils/mocks/movies')

/**
 * Pruebas: toma el archivo de servicios y cambia la ruta de la libreria de mongo
 * por la clase exportada de la MongoLibMock. Esto daria como resultado
 * una clase con la misma estructura pero que los metodos de la libreria
 * de mongo serian mas bien hacia el mock, y se crea una instancia de ella.
 */
describe('services - movies', function() {
  const MoviesService = proxyquire('../services/movies.js', {
    '../lib/mongo': MongoLibMock
  })
  const moviesService = new MoviesService()
  describe('when getMovies method is called', async function() {

    /**
     * Prueba hace una peticion al servicio getMovies, como este servicio manda
     * a llamar al metodo getAllStub obtenemos una senial mediante sinon 
     * de que fue llamado el metodo
     * getAllStub es el metodo que implantamos mediante proxyquire
     * Si efectivamente se llamo, recibiriamos un true del assert, y con esto una prueba exitosa
     */
    it('should call the getAll MongoLib method', async function() {
      await moviesService.getMovies({})
      assert.strictEqual(getAllStub.called, true)
    })
    
    /**
     * Prueba: que la respuesta obtenida del servicio getMovies sea igual a la que esperamos
     * hacemos la peticion y guardamos el resultado, recuerda que se hace al mock de lib
     * tomamos el objeto de la lista de datos del mock de movies
     * con assert verificamos que sea estrictamente igual
     */
    it('should return an array of movies', async function() {
      const result = await moviesService.getMovies({})
      const expected = moviesMock
      assert.deepEqual(result, expected)
    })
  })
})

Alguien me dice porfa o me termina de definir claramente porque algunos codigos se llaman utilidad? Cuando buenamente puedan y sepan me dicen por favor.

Chicos los tests son s煤per importantes, no se rindan!!!

Reemplazo Libreria Mongo

Si no usan proxuquire con el metodo load, no va a funcionar esto que hace el profesor. Debe ser nuevo

 const MoviesServices = proxyQuire.load('../services/movies', {
        '../lib/mongo': MongoLibMock
    });

El nuevo test me genera error de timeout, intent茅 agregando el done() como me sugiere el mensaje de error pero no cambia nada. Mi codigo es el siguiente.

describe('when getMovies method is called', async function () {
        it('should call the getAll MongoLib method', async function (done) {
            await moviesServices.getMovies({})
            assert.strictEqual(getAllStub.called, true)

            done()
        })
    })

sinon

los gigachads como tu y como yo, somos superiores al resto

<h4>Ahora en nuestro archivo de test鈥</h4>

importamos lo nesesario 鈥

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

const { MongoLibMock, getAllStub } = require('../utils/mocks/mongoLib');

const { moviesMock } = require('../utils/mocks/movies');

reemplazamos la clase que llama a mongoDB por una que llama a los mocks

describe('services - movies', function() {
  const MoviesServices = proxyquire('../services/movies', {
    '../lib/mongo': MongoLibMock
  });

Ahora llamos a nuestro servicio con la nueva clase reemplazada, de forma asincrona, si una lo tiene la de arriba tambien debe

una vez ejecutado el moviesService.getMovies({}); recuerda que este llama en alg煤n momento la funci贸n getAllStub

luego preguntamos la funci贸n getAllStub. tiene una propiedad llamada called, esta es extrictamente igual a true, es decir getAllStub.called === true solo que de esta forma el test responde en consola que se cumple o no

describe('when getMovies method is called', async function() {
    it('should call the getall MongoLib method', async function() {
      await moviesService.getMovies({});
      assert.strictEqual(getAllStub.called, true);
    });

El siguiente es lo mismo pero esta vez comparar谩 los resulatados

en este caso si guardamos en una variable el resultado y usamos deepEqual ya que compara a varios niveles profundo, queremos esto porque es un objeto

it('should return an array of movies', async function() {
      const result = await moviesService.getMovies({});
      const expected = moviesMock;
      assert.deepEqual(result, expected);
    });
  });

Una carrera completa de test estaria de lujo!

Para quienes tengan el siguiente error en los test por ESLint

'describe' is not defined.eslint (no-undef)

Se tiene que sumar la siguiente informaci贸n en el archivo .eslintrc

module.exports = {
  env: {
    /.../
    mocha: true,
  },
/.../
};

interesante Mocha para hacer los test

hay que leerse primero la documentation de esos m贸dulos para poder entender mejor

Este curso ha sido el que m谩s me ha costado de la Escuela de Javascript. Creo que explican las cosas muy por encima y da poco contexto de lo que hace.
Sin embargo en cuanto a temas esta muy completo

Los que no entendieron muchas cosas, tomen en cuenta que no es un curso de testing, el testing es TODO un tema, de hecho hay roles en desarrollo de QA que solo se dedican a testear apps, tranquilos, vayan a documentaci贸n busquen un curso de testing

potatzio?

Me exploto un poco la cabeza jajaj Esta un poco complejo 鈥 pero como todo en programacion (practica) 馃槃

bastante avanzado y yo con poca experiencia 馃槙

De a poco se va volviendo mas accesible entenderle a Guillermo, pasa que usa demasiados t茅rminos que no explica, o los explica por encima, entiendo que se supone que ya este curso es de nivel 鈥渁vanzado鈥, pero es importante que los nombres que salen de lo cotidiano sean explicados, en mi primer clase de programaci贸n presencial un muy buen maestro nos dijo: 鈥淓l esquimal reconoce mas de 7 tipos de blanco en su d铆a a d铆a, gracias a que los puede nombrar鈥. Vaya bien que me ha hecho esa frase.

馃槓馃槬馃槪

Los tests son un paso fundamental del desarrollo de software, nos ayuda en la mantenibilidad de nuestro c贸digo, puesto que cuando alteramos algo o incluimos nuevas caracteristicas, identificamos de forma r谩pida qu茅 se pudo romper del resto del c贸digo.

Cuando trabajamos con esta metodolog铆a es importante tener en cuenta para que sirven en describe y el it.

describe Nos ayuda a definir el contexto del test, con el identificamos en primera instancia los test que componen el bloque de pruebas que estamos desarrollando, en este caso ser铆a:

describe('services - movies', function () {
	<some code>
});

Luego de identificar el bloque general de las pruebas que vamos a desarrollar, pasamos a configurar el entorno de nuestro test, en esta clase encontramos en esta configuraci贸n encontramos el llamado a todos nuestros servicios que queremos probar, y adem谩s, estructuramos el entorno en que lo probaremos, en este caso, con el mongo de prueba que configuramos en 鈥渕ongoLib.js鈥

Luego de identificar el bloque de pruebas y prearar las configuraciones iniciales, pasamos a crear nuestros test individuales, para identificarlos nos apoyamos de de describe con su funci贸n callback que incluir谩 el test. Cabe destacar que la estructura de un describe es:

describe('Mensaje que identifica nuestro bloque o nuestro test', function() { callback con la l贸gica del entorno o de los test individuales }); 

En este caso, cuando desarrollamos test individuales, nos aseguramos de incluir el async en la llamada de la funci贸n callback, esto es para realmente esperar la respuesta de nuestro entorno e identificar que est谩n funcionando bien los servicios.

Luego de describir el test individual hacemos un llamado a it, it viene a representar el test que identificamos previamente, en el primer argumento pasaremos el mensaje de nuestro test espec铆fico, para identificar que deber铆a ocurrir para que el test sea aprobado, luego, en la funci贸n callback que pasamos en el segundo parametro volvemos a llamar al async para esperar nuestra respuesta del test.

Finalmente, dentro del callback de it, vamos a pasar el c贸digo que buscamos probar, en este caso es el servicio de getMovies(). Con lo que luego en caso de que el llamado se efect煤e correctamente el assert pasar谩 el valor de true validando nuestro test.

Esto resuelve las async que estuvimos configurando previamente y finalmente en consola mocha nos arroja un check por tener el test aprobado.

De esta forma luego en caso de efectuar un cambio a futuro en nuestros servicios podremos evaluarlo en un entorno seguro de forma r谩pida.

Disculpen lo extenso, aprovech茅 la explicaci贸n para tambi茅n repasar yo 馃槂