Inicio del curso

1

驴Qu茅 vamos a construir en el curso avanzado de Node.js?

Introducci贸n a Node.js

2

Conoce qu茅 es node.js

3

Caracter铆sticas de la plataforma Node.js

4

驴Qu茅 tipo de aplicaciones podemos desarrollar con Node.js?

Preparando el entorno de Desarrollo

5

C贸mo instalar Node.js en macOS

6

C贸mo instalar PostgreSQL y Redis en macOS

7

C贸mo instalar Visual Studio Code en macOS

8

C贸mo instalar Ansible en macOS

Arquitectura del Proyecto (Platziverse)

9

Arquitectura y Componentes del proyecto

Introducci贸n a protocolos y patrones de aplicaciones en tiempo real

10

C贸mo funciona el modelo Pub/Sub en MQTT y Web Sockets

Creando M贸dulo de Base de Datos (platziverse-db)

11

Estructura b谩sica de un m贸dulo de Node.js

12

Definici贸n de entidades de base de datos

13

Implementaci贸n de modelos con sequelize

14

Implementaci贸n de un m贸dulo b谩sico de base de datos

15

Implementaci贸n de script de inicializaci贸n de base de datos

16

Creando una advertencia sobre el borrado de base de datos

17

Introducci贸n a pruebas unitarias con Ava.js

18

Introducci贸n a code coverage con nyc

19

C贸mo hacer Mocks y Stubs con Sinon

20

Creaci贸n de fixtures y definici贸n b谩sica del servicio de Agent

21

Implementaci贸n de findbyId y pruebas en el servicio Agent

22

Implementaci贸n de createOrUpdate

23

Revisi贸n del servicio Agent

24

Implementaci贸n del servicio Metric

25

Realizando un ejemplo con el m贸dulo de base de datos

26

Reto: C贸mo modificar el script de inicializaci贸n de la base de datos

Construyendo un servidor en tiempo real para Internet de las Cosas con Mosca/MQT

27

Definici贸n de un Broker de Mensajer铆a

28

Definici贸n de los tipos de mensajes

29

Implementaci贸n del servidor MQTT

30

C贸mo recibir mensajes

31

C贸mo integrar el servidor MQTT con la base de datos

32

C贸mo almacenar la informaci贸n del agente y reportar el agente conectado

33

C贸mo almacenar la informaci贸n de las m茅tricas

34

Probando el servidor MQTT (Ejemplo con mqtt client)

Construyendo el agente de monitoreo (platziverse-agent)

35

C贸mo implementar un custom EventEmitter usando ES6 classes

36

Definiendo un timer de ejecuci贸n continua (setInterval)

37

Implementaci贸n del cliente MQTT

38

Implementaci贸n de m茅tricas personalizadas

39

Probar agent (ejemplo)

Construyendo una API REST con Express (platziverse-api)

40

Implementaci贸n de un servidor b谩sico con express

41

Definici贸n de rutas del API

42

Implementaci贸n de manejo de errores con express

43

Pruebas b谩sicas de Integraci贸n con Ava y supertest

44

Integraci贸n con el m贸dulo de base de datos

45

Implementaci贸n de ruta del API

46

Pruebas de Integraci贸n con Ava, Supertest y Sinon

Asegurando nuestra API REST con JWT

47

Definici贸n de JWT

48

Asegurando nuestra API con express-jwt

49

Modificando las pruebas de integracion

50

Implementando permisos con express-jwt-permissions

Creando un Dashboard Web en tiempo real con WebSockets (platziverse-web)

51

Implementaci贸n de un servidor web est谩tico con express

52

Integrando socket.io con express

53

Integrando agente de monitoreo con socket.io

54

Implementaci贸n de rutas proxy con la API

55

Presentaci贸n de nuestro cliente frontend en Vue.js

56

Integraci贸n del cliente frontend con API (Metric)

57

Integraci贸n del cliente frontend con socket.io (Metric)

58

Integraci贸n del cliente frontend con API (Agent)

59

Integraci贸n del cliente frontend con socket.io (Agent)

Creando un Dashboard para la terminal en tiempo real con Blessed (platziverse-cl)

60

Implementaci贸n de un CLI B谩sico con Node

61

Introducci贸n a Blessed / Blessed Contrib

62

Implementaci贸n del layout b谩sico con Blessed Contrib

63

Integraci贸n con el agente de monitoreo 1

64

Integraci贸n con el agente de monitoreo 2

65

Integraci贸n con el agente de monitoreo 3

Depurando Aplicaciones Node.js

66

Utilizando longjohn para mejores stacktraces

67

Depurando en Desarrollo con node --inspect

68

Depurando en Desarrollo con Visual Studio Code

Preparando nuestra aplicaci贸n para producci贸n

69

Preparando Proyecto para Producci贸n 1

70

Preparando Proyecto para Producci贸n 2

71

Creaci贸n de scripts para despliegue con Ansible

72

Probando el database rol con Vagrant

73

Creando scripts del rol de platziverse db y mqtt (script de automatizaci贸n .yml)

74

Terminando los scripts faltantes

75

Creaci贸n de servidores en DigitalOcean

Desplegando nuestra aplicaci贸n a producci贸n

76

Ejecutando los Scripts de Despliegue

77

Utilizando Aplicaci贸n en Producci贸n y cierre del curso

Bonus: Utilizando platziverse-agent en BeagleBone Black y Raspberry PI

78

Implementaci贸n platziverse-agent con Johnny-Five

No tienes acceso a esta clase

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

C贸mo hacer Mocks y Stubs con Sinon

19/78
Recursos

Vamos a crear unos servicios que van a utilizar unos modelos, y estos son los que se van a conectar a la base de datos. Sequelize se encarga de probar los modelos.

Aportes 54

Preguntas 10

Ordenar por:

Los aportes, preguntas y respuestas son vitales para aprender en comunidad. Reg铆strate o inicia sesi贸n para participar.

Hola Para los que ven este video a mediados del 2018, les dejo este par de ajustes segun la actualizaci贸n en documentaci贸n en sinon JS

Crear un sandbox:

 sandbox = sinon.createSandbox()

Restablecer un sandbox:

sandbox && sandbox.restore()

Documentaci贸n Sinon JS - Sandboxes

Agradezco este video va bien profundo en lo que es preparar unas pruebas unitarias.

Saludos!!

en las versiones recientes de sinon no se usa

sinon.sandbox.create()
sinon.sandbox.restore()

esto se convierte a

sinon.createSandbox()
sinon.resetHistory()

A partir de este v铆deo me he dado cuenta que hace un buen rato que miro el c贸digo de Juli谩n y lo copio en mi Visual Studio Code como un papagayo sin entender nada鈥 Echo en falta quiz谩s un v铆deo que de vez en cuando haga un repaso-resumen de las cosas que se han ido implementando.

驴Quiz谩s me he saltado un curso m谩s liviano que explique los conceptos b谩sicos de node.js antes de meterme en el curso avanzado?

O quiz谩s yo soy m谩s lento que el resto, no lo descarto xD.

Para versiones actuales de sinon me toco realizar los siguientes cambios:

let sanbox = null

test.beforeEach(async () => {
  sanbox = sinon.createSandbox()
  AgentStub = {
    hasMany:sanbox.spy()
  }
  ...
})

test.afterEach(() => {
  sanbox && sanbox.restore()
})

Hola, me aparecia error en sinon.sandbox.restore().
error sinon.sandbox.restore() is not a function.

Resuelto de la siguiente forma

sandbox.restore()

Adjunto enlace para consulta:

http://sinonjs.org/releases/v2.0.0/sandbox/

asi es como cambia el c贸digo en las versiones actuales, se llama directamente createSandbox en lugar de sinon.sandbox

de igual manera con afterEach(), directamente es sandbox.restore() sin necesidad de llamar a sinon

test.beforeEach(async () => {
  sandbox = sinon.createSandbox()
  ...
}
test.afterEach( () => {
  sandbox && sandbox.restore()
})

Algunas definiciones de la clase:

  • Stub, objeto que es similar en su funcionalidad al objeto original (nuestro modelo), pero que la respuesta y los argumentos de entrada est谩n previamente especificados con una librer铆a o estrategia. Objetos falsos que se van a comportar de manera similar a los objetos reales.

  • Spy es una funci贸n espec铆fica que permite hacer preguntas como: 驴Cuantas veces fue llamada una funci贸n?, 驴con que argumentos?, es muy 煤til a la hora de hacer pruebas.

  • Sandbox ambiente especifico de sinon que va a funcionar para un caso particular (no de manera global). Cuando se termine de ejecutar la prueba se reinicia el sandbox.

Instalate un paquetico por NPM

Me gustar铆a una clase bonus s贸lo sobre testing. tengo que ver el video varias veces para darle sentido al serial, beforeEach afterEach, sandbox, proxyquire y sinon

Hola, para los que se atreven a realizar este excelente curso con un poco de desactualizaci贸n como yo. En esta 茅poca ya existe un test runner llamado jest, mantenido por facebook que facilita un poco la construcci贸n de las pruebas automatizadas. Para aquellos que quieran lanzarse con ello y no esten tan empapados, pueden ver el curso de Jest que est谩 m谩s adelante en la escuela de backend con JS o mirar mi implementaci贸n en mi repositorio.

Este test runner, no necesita la creaci贸n de un isolated env como lo es el sandbox ni un proxyquire. El realiza esa gesti贸n internamente. Y para la restauraci贸n o limpieza de ese 鈥渟andbox鈥, jest ofrece la funci贸n clearAllMocks la cual puede ser llamada en los hooks muy similar a como se hace en esta clase.

Esas son algunas conclusiones que he sacado personalmente al hacer ese update de algunas dependencias como el test runner. Si alguien es m谩s experto en el tema agradezco me corriga.

Hola Para lo que est茅n viendo este video en 2021 hay dos peque帽os cambios en sinon 鈥渟inon.createSandbox()鈥 y 鈥渟inon.restore()鈥

test.beforeEach(async () => {
  sandbox = sinon.createSandbox()

  AgentStub = {
    hasMany: sandbox.spy()
  }

  const setupDatabase = proxyquire('../', {
    './models/agent': () => AgentStub,
    './models/metric': () => MetricStub
  })

  db = await setupDatabase(config)
})

para que el test pase sin errores es necesario cambiar:

test.afterEach(t => {
  sandbox && sinon.sandbox.restore()
})

por

test.afterEach(t => {
  sandbox && sandbox.restore()
})

y tambien:

test.beforeEach(async () => {
  sandbox = sinon.sandbox.create()
  AgentStub = {
    hasMany: sandbox.spy()
  }

por

test.beforeEach(async () => {
  sandbox = sinon.createSandbox()
  AgentStub = {
    hasMany: sandbox.spy()
  }

Otra definici贸n de STUBS: 鈥渆n el contexto del testeo del software, un trozo de c贸digo usado como sustituto de alguna otra funcionalidad. Un stub puede simular el comportamiento de c贸digo existente (tal como un procedimiento en una m谩quina remota) o ser el sustituto temporal para un c贸digo a煤n no desarrollado鈥

Y comparto el link del sitio de SINONjs en el que se encuentra un poco m谩s de documentaci贸n sobre el tema.

Usamos los stubs para garantizar que se hacen llamadas a las funciones adecuadas, abstraiendo asi las llamadas de sequelize, las cuales como son de una libreria externa ya testeada no debemos preocuparnos por testearla.

Instalaci贸n de sinon

creo que ser铆a genial y muy 煤til tener cursos de s贸lo pruebas unitarias鈥 ese tema me hace sentir muy muy muy perdido 馃槮

Creo que el msj que pasamos al m茅todo t.true() deber铆a ser negando. Es decir que el AgentModel.hasMany no fue llamado.

test.serial('Setup' , () => {
  t.true(AgentStub.hasMany.called , "AgentModel.hasMany wasn't executed")
   t.true(AgentStub.hasMany.calledWith(MetricStub), 'Argument should be the model')
   t.true(MetricStub.belongsTo.called, `MetricModel.belongsTo wasn't executed`)
   t.true(MetricStub.belongsTo.calledWith(AgentStub), 'Argument should be the model')
})

Ya que este se imprime solo cuando AgentStub.hasMany.called retorna el valor false

demasiada informaci贸n en muy poco tiempo. me frustre 馃槥

Por si alguien lo est谩 haciendo con jest, este c贸digo me funciona

'use strict'

let config = {
    logging: function(){},
}

let mockMetricModel = {
    belongsTo: jest.fn(),
}

let mockAgentModel = null
let db = null

beforeEach(async () => {
  mockAgentModel = {
    hasMany: jest.fn(),
  }

  const setupDatabase = require('../../index')

  jest.mock('../../models/agent', () => jest.fn(() => mockAgentModel))
  jest.mock('../../models/metric', () => jest.fn(() => mockMetricModel))

  db = await setupDatabase(config)
})

afterEach(() => {
    jest.resetModules()
    jest.clearAllMocks()
})

describe('Agent', () => {
  test('The agent should exists', () => {
    expect(db.Agent).toBeDefined()
  })

  test('setupAgentModel.hasMany should be called', () => {
    expect(mockAgentModel.hasMany).toHaveBeenCalled()  
  })

  test('setupMetricModel.belongsTo should be called', () => {
    expect(mockMetricModel.belongsTo).toHaveBeenCalled()  
  })

  test('setupAgentModel.hasMany should be called with mockMetricModel', () => {
    expect(mockAgentModel.hasMany).toHaveBeenCalledWith(mockMetricModel)
  })
  
  test('setupMetricModel.belongsTo should be called with mockAgentModel', () => {
    expect(mockMetricModel.belongsTo).toHaveBeenCalledWith(mockAgentModel)
  })
})

Error diciendo, sinon.sandbox.restore is not a function, en vez cambie esa linea a lo siguiente.

test.afterEach(() => {
  sandbox && sandbox.restore() // Eqv: if (sandbox) sinon.sandbox.restore();
})

que significa &&?

sandbox && sinon.sandbox.restore()

Le pone mucho color el profe con las pruebas, y los alumnos m谩s se enredan

el contenido esta muy interesante y se nota que el lo comenta desde la experiencia por eso aveces uno como que se queda por que como no lo ha hecho o no ha hecho las malas practicas no sabe el por que de algunas razones , sin embargo leer la documentaci贸n de lo que usa es una buena opci贸n

el npm test me bota que la prueba no paso, a qu茅 se debe?

  • 鈥榮etupAgentModel is not a function鈥

VSCode en Windows 10, al lado de la l铆nea

const sinon = require('sinon')

muestra 鈥677.4k (gzipped: 235k)鈥 en rojo, me imagino que debe ser una advertencia sobre el tama帽o de la librer铆a, es problem谩tico eso?

Como serian las pruebas para la liberia request-promise-native usando sinon.?

Este seria mi implementacion pero no esta funcionando correctamente

const request = require(鈥榬equest-promise-native鈥)
let resolveStub = sandbox.stub(request, 鈥楻equest鈥).withArgs(options).resolves(data)

Donde 鈥渙ptions鈥 son los datos del conexion a la API y 鈥渄ata鈥 es el resultado esperado.

驴a todos los imports del modelo en index se le deben de crear un stub?

Quise probar los stubs en un proyecto diferente y cuando hago el test me aparece el siguiente error

TypeError {
    message: 'Cannot read property \'belongsTo\' of undefined',
  }```
aca esta el codigo:
https://github.com/chaqui/backendLibreria/blob/master/backendLibreria-db/tests/TC_Persona-tests.js

Estoy intentando conseguir hacer los 鈥渟tubs鈥 con Jest y no consigo hacerlos funcionar

Les dejo el codigo sin los stubs por si alguien sabe como implementarlo, Gracias!

import setupDatabase from '..';

const config = {
  logging() {},
};

let db = null;

beforeEach(async () => {
  db = await setupDatabase(config);
});

describe('Agent', () => {
  test('Agent service should exist', () => {
    expect(db.Agent).toBeTruthy();
  });

  test('Setup', () => {
    // expect(MetricStub.belongsTo).toHaveBeenCalled();
    // expect(Agent).toHaveBeenCalled();
  });
});

Me parece interesante compartir esto que esta en la documentacion de AVA

Mocha requires you to use implicit globals like describe and it with the default interface (which most people use). It's not very opinionated and executes tests serially without process isolation, making it slow.

Me qued贸 una duda con respecto a cual es la funci贸n del sandbox, lo 煤nico que entend铆 es que es una forma de depurar mis stub, para que sean 鈥渓impiados鈥 cada vez que se realice mi test. Pero estuve haciendo unas pruebas, remov铆 todo lo que era sandbox e incluso quit茅 mi hooks .afterEach()

test.beforeEach(async () => {
    /*sandbox = sinon.createSandbox()*/
    AgentStub = {
        hasMany: sinon.spy()
    }
    const setupDatabase = proxyquire('../', {
        './models/agent': () => AgentStub,
        './models/metric': () => MetricStub
    })
    db = await setupDatabase(config)
})

test('Agent' , t => {
    t.truthy(db.Agent , 'Agent should exist')
}) 

test.serial('Setup', t => {
    t.true(AgentStub.hasMany.called, `AgentModel.hasMany wasn't executed`)
    t.true(AgentStub.hasMany.calledWith(MetricStub), 'Argument should be the model')
    t.true(MetricStub.belongsTo.called, `MetricModel.belongsTo wasn't executed`)
    t.true(MetricStub.belongsTo.calledWith(AgentStub), 'Argument should be the model')
})

/*test.afterEach(async () => {
           sandbox && sinon.resetHistory()
}) */ 

realic茅 la primera prueba, y todo sucedi贸 okay, como deb铆a ser, pero ahora hice lo siguiente.

 // AgentModel.hasMany(MetricModel)
  MetricModel.belongsTo(AgentModel)

Como se supone que el sinon est谩 ya 鈥渓lamado鈥 deber铆a recordar el test anterior 驴o no? Resulta que al realizar el prueba, me marc贸 que el has many no fue llamado. Entonces me hace creer que el sandbox no cumple ninguna funci贸n y me confunde todo esto.

Tambi茅n investigu茅 que mi objeto sinon a partir de la versi贸n 5.0, ya es un sandbox por defecto, pero recuerda que nunca hice el reset de este, ya que coment茅 el afterEach()

no se que error tengo este es mi codigo:

'use strict'

const test = require('ava')
const proxyquire = require('proxyquire')

let config = {
  logging: function () {}
}

let MetricStub = {
  belongsTo: function () {}
}

let AgentStub = null
let db = null

test.beforeEach(async () => {
  AgentStub = {
    hasMany: function () {}
  }

  const setupDatabase = proxyquire('../', {
    './models/agent': () => AgentStub,
    './models/metric': () => MetricStub
  })

  db = await setupDatabase(config)
})

test('Agent', t => {
  t.truthy(db.Agent, 'Agent service should exist')
})

y me sigue diciendo que proxyquire no esta definido:

 C:\Users\Hewllet\Videos\aaa\platziverse\platziverse-db\tests\agent-tests.js:21:25: 'proxyquire' is not defined.

Proxyquire sobreescribe los modelos

Estoy teniendo problemas con proxyquire, tengo la dependencia instalada pero al correr el test me sigue diciendo que proxyquire no esta definido, ya he desinstalado y vuelto a instalar proxyquire y no se que hacer

"dependencies": {
    "chalk": "^2.4.1",
    "debug": "^3.1.0",
    "defaults": "^1.0.3",
    "inquirer": "^6.0.0",
    "pg": "^7.4.3",
    "pg-hstore": "^2.3.2",
    "sequelize": "^4.38.0"
  }
}
'use strict'

const test = require('ava')
const proxyquire = require('proxyquire')

let config = {
  logging: function () {}
}

let MetricStub = {
  belongsTo: function () {}
}

let AgentStub = null
let db = null

test.beforeEach(async () => {
  AgentStub = {
    hasMany: function () {}
  }

  const setupDatabase = proxyquire('../', {
    './models/agent': () => AgentStub,
    './models/metric': () => MetricStub
  })

  db = await setupDatabase(config)
})

test('Agent', t => {
  t.truthy(db.Agent, 'Agent service should exist')
})
C:\Users\Hewllet\Videos\aaa\platziverse\platziverse-db>npm run lint

> [email protected] lint C:\Users\Hewllet\Videos\aaa\platziverse\platziverse-db
> standard

standard: Use JavaScript Standard Style (https://standardjs.com)
  C:\Users\Hewllet\Videos\aaa\platziverse\platziverse-db\tests\agent-tests.js:21:25: 'proxyquire' is not defined.

Corro el comando npm i sinon --save-dev y el comando npm i --save-dev proxyquire y no se agregan a las dependencias de desarrollo. Alguien sabe porque?

{
  "name": "platziverse-db",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "DEBUG=platziverse:* nyc --reporter=lcov ava tests/* --verbose",
    "setup": "DEBUG=platziverse:* node setup.js",
    "lint": "standard",
    "lint-fix": "standard --fix"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "ava": "^3.8.2",
    "nyc": "^15.0.1",
    "sqlite3": "^4.2.0",
    "standard": "^14.3.4"
  },
  "dependencies": {
    "chalk": "^4.0.0",
    "debug": "^4.1.1",
    "defaults": "^1.0.3",
    "inquirer": "^7.1.0",
    "pg": "^8.2.0",
    "pg-hstore": "^2.3.3",
    "sequelize": "^5.21.9"
  }
}
npm i proxyquire -D

Tambien pueden cambiar el
`sandbox= sinon.sandbox.create()``
por

``sandbox= sinon.createSandbox()

Wow, cada vez me sorprendo mas en Platzi, este curso est谩 a un nivel profesional

Tener en cuenta cambiar sinon.sandbox.create() por sinon.createSandbox() ya que sandbox.create() ahora es obsoleto

test.beforeEach(async () => {
  sandbox = sinon.createSandbox()
....

Dejo asentado que hay un posible problema entre sqlite 3.1.9 y la instalacion de sinon

Me sali贸 error al querer instalar sinon. La soluci贸n la encontr茅 en stackoverflow.

S贸lo tienes que borrar el archivo package-lock.json e intentar de nuevo instalar sinon.

No entend铆 la diferencia entre las aserciones true y thuty en AVA

Apartir de la instalacion del modulo de sqlite3 estoy teniendo problemas con la instalacion de los modulos, esto a que se debe?

saludos

Hola, el test.beforeEach(async () => { 鈥 Podr铆amos quitarle lo de async? No parece que tenga que ser asyncrono necesariamente, no? En el afterEach no hemos puesto que sea asyncrona

En caso de querer hacer el stub pero ES6 sin usar proxyquire, es posible realizar de alguna forma tal stub, ya que al crear el stub de AgentModel el test no reconoce el metodo findById.
Alguna gu铆a al respecto? se agradece de antemano

Creo que nos tardamos m谩s en realizar pruebas que en implementar el m贸dulo. Pero sin duda hacer pruebas hace que escribas mejor c贸digo.

Buenas, tengo un par de dudas:

  1. No termino de entender cual es la diferencia del objeto sandbox con respecto al m茅todo spy de sinon y porque tengo que generar un stub del modelo Agent por cada test y no hago lo mismo con el de Metric.
  2. 驴No puedo definir el objeto sandbox por fuera del beforeEach? Si de todas formas lo estoy reiniciando cada vez que finaliza cada test.
  3. No me termina de cerrar que hace la siguiente linea de c贸digo:

sandbox && sinon.sandbox.restore()

Perd贸n por tantas preguntas, esta muy bueno el curso.

隆Muchas gracias!

Si sientes que estas perdido apartir de este video es porque probablemente lo estes, yo tambien me sent铆 asi. Lo que hice para dejar de sentirme asi fue regresar al c贸digo y cambiar l铆neas para hacer fallar el test, comentar cada paso que se est谩 haciendo en los tests y en los otro m贸dulos, volver a ver los videos, tomar谩 tiempo pero vale la pena.

Para los que no estamos muy familiarizados con la parte de pruebas, les recomiendo este enlace

Me ayud贸 a entender un poco que son exactamente los Stubs y Mocks y as铆 pude ver porque el profe hacia las cosas en el c贸digo!

Hay algo fundamental que aun no se entiende, el concepto de 鈥渦ni-test鈥. Cualquiera que realmente quiera entender porque se hace mocking y stub primero tiene que entender este concepto.

Creo que de estos temas de testeo podria salir un curso completo que creo debe ser obligatorio en la carrera de js

Buenas, que alternativas tengo a proxyquiere si estoy usando modules de ES6 (import, export) ??