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 = ‘movies’;
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 “stubs” 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 “avanzado”, 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: “El 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 “mongoLib.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 😃