Bienvenida e Introducción

1

¿Qué son las pruebas unitarias?

2

¿Por qué hacer pruebas unitarias?

Creando un framework de pruebas básico

3

Mi primera prueba unitaria en JavaScript

4

Las funciones expect() y it()

5

Organizando el código para correr en la web

6

Organizando el código para correr utilizando nodejs

Análisis estático de código

7

Herramientas de análisis estático de código

8

ESLint: Agregando alertas a nuestro código con ECMA Script

9

Herramientas de corrección de estilo

10

Herramientas de tipado

Trabajando con Jasmine en el frontend

11

Profundización en SpyOn: Comandos más utilizados y cómo ponerlos a prueba

12

Configurar un ambiente de trabajo para trabajar con el framework jasmine

13

Configurar Jasmine utilizando Node.js

14

Primer set de pruebas con Jasmine

15

Diccionario Jasmine

Probando Nodejs apps con Jasmine

16

Introducción al módulo de testing del lado del servidor

17

Configurando el proyecto Jasmine utilizando npm

18

Agregando Plugins a Jasmine

19

Configurando nuestro reporter

20

Pruebas en el servidor: Verificando un status 200 en GET

21

Pruebas en el servidor: Probando el método GET y Reto con FindByID

22

Pruebas en el servidor: Probando el método POST (request to server)

23

Pruebas en el servidor: Probando el método POST (request to PDF)

Probando Angular apps con Jasmine

24

Tipos de pruebas

25

Pruebas en el frontend: Probando el componente principal (App)

26

Configurando los ciclos de vida

27

Creando las pruebas del formulario: Configuración

28

Creando las pruebas necesarias para un formulario. (Primeras pruebas)

29

Probando el caso de exito al guardar un elemento en el servidor.

30

Trabajando con event emitters

31

Testeando ngZone y navegación.

32

Configurando el TestBed de el componente PINs

33

Creando un espia sobre el objecto window

Pruebas de integración de Angular apps con Jasmine

34

Ejecutando funciones a través de eventos en el template

35

Probando la navegación

36

Probando servicios con HTTP

37

Completando las pruebas del servicio HTTP

38

Cierre del curso

Aún no tienes acceso a esta clase

Crea una cuenta y continúa viendo este curso

Curso de Unit Testing para MEAN con Jasmine

Curso de Unit Testing para MEAN con Jasmine

Cristian Daniel Marquez Barrios

Cristian Daniel Marquez Barrios

Pruebas en el servidor: Probando el método POST (request to server)

22/38
Recursos

Vamos a usar axios: una librería que nos ayuda a consultar y enviar datos a las URLs que le indiquemos con una sintaxis un poco diferente a la de la librería request. Podemos usarla, por ejemplo, para hacer consultas a nuestra propia aplicación para comprobar que obtenemos la información que esperamos.

Instalación de axios:

npm install axios --save-dev

Vamos a probar el caso de éxito del método POST de nuestra API: la aplicación debe responder correctamente cuando los usuarios envían URLs de archivos PDF o páginas con código HTML común y corriente.

En este caso, vamos a utilizar datos “falsos” para correr las pruebas: en vez de descargar los recursos para consumir un PDFs o una páginas web, nosotros mismos vamos a escribir los datos con los que interactúa nuestro código para comprobar que la aplicación responde correctamente.

Aportes 4

Preguntas 1

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.

En el callFake el primer parametro que recibe es Pin, por lo que si no lo pones da error el test con respuesta 500.

spyOn(Pins, ‘create’).and.callFake((pin, callBack )=> {
callBack(false, {});
});```

Tambien falta declarar

var requestPromise = require(‘request-promise-native’);

Creo que esta explicación se podría mejorar, es mas una demostración de sus conocimientos que una guía para aprender porque se hacen las cosas

Yo hice el ejercicio con request pero no entendí para que era el objeto post

it("200", done => {
      spyOn(Pins, "create").and.callFake((pin, callBack) => {
        callBack(false, {});
      });
      spyOn(requestPromise, "get").and.returnValue(
        Promise.resolve(
          '<title>Platzi</title><meta name="description" content="Platzi description">'
        )
      );

      const assets = [{ url: "http://platzi.com" }];

      request.post(
        "http://localhost:3000/api",
        {
          json: {
            title: "title",
            author: "author",
            description: "description",
            assets
          }
        },
        (error, response, body) => {
          expect(response.statusCode).toBe(200);
          done();
        }
      );
    });```

Quiero hacer una prueba de un caso más complejo. tengo el la siguiente clase Trxs:

const Mysql2Base = require("./Mysql2Base");
const TrxDetails = require("./../TrxDynamo");
const AuthorizationHelper = require("./../../helpers/authorization.helper");


class Trxs extends Mysql2Base {
   constructor() {
        super();
        this.table = "trxs";
        this.services_table = "servicios";
   } 

   getAll(data){
        return new Promise((resolve, reject) => {    
        let query = 'some_query'
            this.write(query).then( async queryResult => {
                try{             
                    queryResult.forEach((element, idx, arr) => {
                        queryResult[idx]["url"]= this.getCompleteUrl(element.idTrx, element.id_session);
                        let trxDetail = new TrxDetails(element.idTrx);
                        let getTrxDetail = await trxDetail.getTrxDetails();
                        if(getTrxDetail.Count > 0 ){
                           /*
				Codigo...
			   */
                        }else{
                            /*
				Codigo...
			   */
                        }
                    });
		    resolve(queryResult);          
                }catch(error){
                    console.log("ERROR", error);
                    reject(error);
                }    
            }).catch(errorQuery => {
                reject(errorQuery);
            });                   
        }   
   }

    getCompleteUrl(id, idSession) {
        return 'http://example.com' + AuthorizationHelper.generateAuthHeader(id, idSession);
    }

}

module.exports = Trxs;

La clase TrxDynamo (llamada TrxDetails en el codigo anterior) es así:

const Trxs = require("./DYNAMODB/Trxs");

class TrxDynamo extends Trxs{
    constructor(idTrx) {
        super();
        this.idTrx = idTrx;
    }
  
    getTrxDetails() {
        return super.getTrxDetails(this.idTrx);
    }
}

module.exports = TrxDynamo;

‘super.getTrxDetails()’ es un método de la clase Trxs (distinta a la primera) que es así:

const DynamoBase = require("./DynamoBase");

class Trxs extends DynamoBase{

    constructor() {
        super();
        this.table = `tabla_trx_dynamo`;
    }
   
    getTrxDetails(idTrx) {
        return new Promise((resolve, reject) => {
            let params = {
                TableName: this.table,
                KeyConditionExpression: "#idTrxs = :id",
                ExpressionAttributeNames: {
                    "#idTrxs": "idTrxs",
                },
                ExpressionAttributeValues: {
                    ":id": `${idTrx}`,
  
                },
            };

            super.executeQuery(params).then(saveResult => {
                console.log(saveResult);
                resolve(saveResult);
            }).catch(errorSave => {
                console.log("No se pudo obtener los datos getTrxDetails");
                reject(errorSave);
            });
        });
    }

}

module.exports = Trxs;

En el spec tengo lo siguiente:

const express = require('express');
const http = require('http');
const Trxs = require('./../models/MYSQL/Trxs');
const TrxDetails = require('./../models/DYNAMODB/Trxs');

app.use(express.json());
app.set('port', 3000);

describe('Transacciones', function() {
	let server;
	let trxs;
	let trxDetail;
	let data = {
		idServicio: '468',
		limit: '10'
	};
	let exampleObject = [
		{
			idTrx: 'id1',
			estado: 'COMPLETADA',
			source: 'WebpayPST'
		},
		{
			idTrx: 'id2',
			estado: 'PENDING',
			source: 'WebpayPST'
		}
	];

	beforeAll(() => {
		server = http.createServer(app);
		server.listen(3000);
		trxs = new Trxs();
		trxDetail = new TrxDetails('id1');
		spyOn(trxs, 'write').and.returnValue(Promise.resolve(exampleObject));
		spyOn(trxDetail, 'getTrxDetails').and.returnValue(Promise.resolve({}));
		trxs.getAll(data);
	});

	afterAll(() => 
		server.close();
	});
	it('debe escribir en trx', function(done) {
		expect(trxs.write).toHaveBeenCalled();
		done();
	});
	it('debe obtener detalles de trx', function(done) {
		expect(trxDetail.getTrxDetails).toHaveBeenCalled();
		done();
	});
	it('debe retornar algo', (done) => {
		expect(trxs.getAll).toBeTruthy();
		done();
	});
});

Al método ‘getCompleteUrl’ puedo acceder mediante spyOn porque es de la misma clase. Y el método ‘write’ pertenece a la clase Mysql2Base que está inicializada en el constructor con el super(), por lo tanto no tengo problema tampoco. Sin embargo, quiero aplicar spyOn al método ‘getTrxDetails’ de la clase Trxs (en el spec lo llamo TrxDetails) que está definido en la segunda clase Trxs que mencioné, es decir, desde getAll() se llama a getTrxDetails y de ahí se llama al getTrxDetails que quiero espiar y no funciona. Obtengo este resultado:

  1. Transacciones
    getTrxDetails id1
    . ✔ debe escribir en trx (22ms)
    F ✖ debe obtener detalles de trx (1 failure) (2ms)
    . ✔ debe retornar algo (1ms)
    Failed Specs:

  2. Transacciones : debe obtener detalles de trx
    Expected spy getTrxDetails to have been called.
    at <Jasmine>
    at UserContext.<anonymous> /home/mauxi/Documentos/ebs-api-dashboard/spec/server.spec.js:64:35
    at <Jasmine>

¿Cómo manejo este casos?

Entiendo que el SPY creado para el requestPromise no se llega a ejecutar en este ejemplo, pero creo comprender que en caso ese código en la lógica de la ruta sea ejecutado entonces devolvería el código visto en clase.

En ese caso es correcto decir que para respuestas asíncronas toca crear SPYs en el test para poder manejar una respuesta controlada en la ejecución del código?