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

Curso de Unit Testing para MEAN con Jasmine

Curso de Unit Testing para MEAN con Jasmine

Cristian Daniel Marquez Barrios

Cristian Daniel Marquez Barrios

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

11/38

Lectura

Jasmine spyOn

La separación de responsabilidades es una de las buenas prácticas que encontramos en un proyecto de software. Separar responsabilidades significa agrupar código de tal manera que cada conjunto se encargue de una tarea específica.

Hablemos ahora de las pruebas unitarias. Cuando probamos un componente, queremos probar las responsabilidades que le estamos delegando al componente y no todo el código ejecutado. Es decir, si el componente A utiliza la función b(), lo que queremos probar es la lógica propia del componente y no el código de la función.

Veamos el siguiente ejemplo:

function GetMonthApi() {
  this.currentMonth = function () {
    return 'May';
  }
  this.nextMonth = function () {
    return 'June'
  }
}
export function MonthCalculator() {
  this.api = new getMonthApi();
  this.getNextMonth = function() {
    return this.api.nextMonth();
  }
  this.getCurrentMonth = function() {
    return this.api.currentMonth();
  }
}

La clase MonthCalculator nos permite calcular el valor del mes actual y el siguiente. Cómo puedes ver, la función getMonthApi es utilizada dentro de la clase. Si ejecutas el set de pruebas asociadas a nuestra clase se ejecuta en Mayo el valor del siguiente mes sería Junio, o si las corres en Enero el siguiente mes sería Febrero. ¿Ves el problema?.

Si ejecutamos código que se encuentre fuera del domino de un componente, nos podemos encontrar con resultados inesperados. Es por ello, que jasmine cuenta con un sistema de espías (spyOn), cuyo objetivo principal es interceptar la ejecución de una función y simular su resultado.

Veamos un poco de código:

El primer método que vamos a probar es el de obtener el mes actual currentMonth. Si la prueba la creamos en mayo, el código debería ser:

describe('MonthCalculator', () => {
  it('returns the current month', () => {
    // Arrange
    const monthCalculator = new MonthCalculator();  
    // Act
    const month = monthCalculator.currentMonth();
    // Assert
    expect(month).toBe('May');
  });
});

Este código tiene un problema. La función currentMonth va a retornar un valor que depende del mes actual.

Como ya te podrás imaginar, el uso de espías resulta bastante útil en este caso debido a que podemos controlar el valor del mes retornado.

Es decir:

describe('MonthCalculator', () => {
  it('returns the current month', () => {
    // Arrange
    const monthCalculator = new MonthCalculator();
    const spy = spyOn(
                 monthCalculator.api,
                 'currentMonth'
               ).and.returnValue('Cristian Month');
    // Act
    const month = monthCalculator.currentMonth();
    // Assert
    expect(month).toBe('Cristian Month');
    expect(spy).toHaveBeenCalled();
  });
});

La instancia del API la tenemos almacenada en la variable this.api de nuestra clase.
Jasmine nos permite interceptar el llamado a nuestro API utilizando la función spyOn. Para ello, como primer parámetro debemos pasar el objeto que contiene el método que vamos a interceptar y como segundo parámetro el nombre del mismo.

Una vez creado nuestro espía, para poder controlar el valor retornado debemos concatenar lo siguiente: .and.returnValue().
Finalmente Jasmine nos permite verificar la ejecución de la función por medio del operador .toHaveBeenCalled().

Cómo reto ve al siguiente enlace, has un fork del proyecto y realiza las pruebas relacionadas con el método nextMonth(). Recuerda crear un espía para eliminar la dependencia con nuestra API.

Finalmente, te dejo un listado de preguntas y respuestas sobre todo lo que puedes hacer con espías:

¿Cómo se crea un espía?

spyOn(obj, 'method') // obj.method es una función

¿Cómo verificar que un método fue llamado?

const ref = spyOn(obj, 'method');
expect(ref).toHaveBeenCalled();
// O directamente
expect(obj.method).toHaveBeenCalled()

¿Cómo verificar que un método fue llamado con un parámetro específico?

const ref = spyOn(obj, 'method');
expect(ref).toHaveBeenCalledWith('foo', 'bar');
// O directamente
expect(obj.method).toHaveBeenCalledWith('foo', 'bar')

¿Cómo puedo verificar el número exacto de ejecuciones de un método?

expect(obj.method.callCount).toBe(2)

¿Cómo espiar en un método sin modificar su comportamiento?

spyOn(obj, 'method').andCallThrough()

¿Cómo puedo cambiar el valor retornado por un método?

spyOn(obj, 'method').andReturn('value')

¿Cómo puedo sobreescribir un método?

spyOn(obj, 'method').andCallFake(() => 'this is a function');

Aportes 14

Preguntas 0

Ordenar por:

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

En este link explican spy0n de una manera mas facil https://scriptverse.academy/tutorials/jasmine-spyon.html

Por acá dejo mi código

import { MonthCalculator } from './months';

describe('MonthCalculator', () => {
  it('returns the current month', () => {
    const m = new MonthCalculator();
    expect(m.api.currentMonth()).toBe('May');
  });

  it('returns the current month', () => {
    const m = new MonthCalculator();
    const spy = spyOn(m.api, 'currentMonth').and.returnValue('First Month');
    expect(m.api.currentMonth()).toEqual('First Month')
    expect(spy).toHaveBeenCalled();
  });

  it('returns next month', () => {
    const m = new MonthCalculator();
    expect(m.getNextMonth()).toBe('June');
  });

  it('returns next month', () => {
    const m = new MonthCalculator();
    const spy = spyOn(m.api, 'nextMonth').and.returnValue('Second Month');
    expect(m.getNextMonth()).toBe('Second Month');
    expect(spy).toHaveBeenCalled();
  });

  it('should spy and verify', () => {
    const monthCalculator = new MonthCalculator();
    const getNextMonth = spyOn(monthCalculator, 'getNextMonth').and.callThrough();
    expect(monthCalculator.getNextMonth()).toBe('June');
    expect(getNextMonth).toHaveBeenCalled();
  });

  it('should spy and verify', () => {
    const monthCalculator = new MonthCalculator();
    spyOn(monthCalculator, 'getNextMonth').and.returnValue('Cristian Month');
    expect(monthCalculator.getNextMonth()).toBe('Cristian Month');
  });
});

Por favor revisar la redacción de este artículo, algunas frases están cortadas o incompletas.

Me frustré muy feo con este curso 😦 me voy a cursar js de nuevo

Estoy batallando por entender cómo funcionan los espías, para eso intenté hacer un espía basado en el ejercicio que se muestra acá pero más realista (que sí regrese el verdadero mes),
.

No estoy pudiendo fakear la fecha para que regrese lo que quiero, ¿alguna recomendación?

.
Código fuente: https://github.com/behagoras/jasmine-tests/tree/currentDate

months.js

function getMonthApi() {
  this.monthNames = ["January", "February", "March", "April", "May", "June",
  "July", "August", "September", "October", "November", "December"];

  this.currentDate = new Date()
  this.cmonth = this.currentDate.getMonth()

  this.currentMonth = function () {
    return this.monthNames[this.cmonth-1]
  }

  this.nextMonth = function () {
    return this.monthNames[this.cmonth]
  }

}

function MonthCalculator() {

  this.api = new getMonthApi();

  this.getNextMonth = function() {
    return this.api.nextMonth();
  }
  this.getCurrentMonth = function() {
    return this.api.currentMonth();
  }
}

months.spec.js

module.exports = MonthCalculator
const MonthCalculator = require('../../src/components/months')

describe('Month Calculator',()=>{
  it('Should return current month',()=>{
    const monthCalculator = new MonthCalculator()
    const date = new Date("June 17, 1995 03:24:00")

    monthCalculator.api.currentDate=date
    const spy = spyOn(monthCalculator.api, 'currentDate').and.resolveTo(date)

    console.log('monthCalculator.getCurrentMonth()',monthCalculator.getCurrentMonth())

    const y = monthCalculator.getCurrentMonth();
    expect(y).toBe('June')

  })
})

¿ Por que no todo se maneja con git hub?

Esta lección está adelantada, ni siquiera se ha explicado como configurara Jasmine en el entorno y ya están poniendo retos…

“Cómo reto ve al siguiente enlace, has un fork del repo …”

Cuál enlace??

Creo que no entendi la ultima pregunta. Yo con el CallFake puedo reescribir la funcion para que haga lo que yo quieaa??

Descarge el projecto, ejecute npm install y despues ng serve.

Me sale este error The serve command requires to be run in an Angular project, but a project definition could not be found

Que onda??

Puede ser que al proyecto le falte el archivo angular.json??

este ejemplo esta malo, empece a realizar las pruebas en una pagina que corre jasmine con karma y de entrada

this.api = new getMonthApi();
// instead
this.api = new GetMonthApi();

simple en el test :

<code>
    // Act
    const month = monthCalculator.currentMonth();

   // esta mal es : 
    // Act
    const month = monthCalculator.getCurrentMonth();
</code>

hola, por acá les dejo un set de pruebas según la tarea que se manda a realizar en el post y les dejo la página donde se puede ver en acción dicho set

describe('spyOn Platzi little class', () => {

  it('returns the current month', () => {
    // Arrange
    const monthCalculator = new MonthCalculator();  
    // Act
    const month = monthCalculator.getCurrentMonth();
    // Assert
    expect(month).toBe('May');
  });

  it('returns the current month spy', () => {
    // Arrange
    const monthCalculator = new MonthCalculator();
    const spy = spyOn(
                 monthCalculator.api,
                 'currentMonth'
               ).and.returnValue('Cristian Month');
    // Act
    const month = monthCalculator.getCurrentMonth();
    // Assert
    expect(month).toBe('Cristian Month');
    expect(spy).toHaveBeenCalled();
  });

  it('returns the next month method', () => {
    // Arrange
    const monthCalculator = new MonthCalculator();  
    // Act
    const month = monthCalculator.getNextMonth();
    // Assert
    expect(month).toBe('June');
  });

  it('returns the next month spy', () => {
    // Arrange
    const monthCalculator = new MonthCalculator();
    const spy = spyOn(
                 monthCalculator.api,
                 'nextMonth'
               ).and.returnValue('February Month');
    // Act
    const month = monthCalculator.getNextMonth();
    // Assert
    expect(month).toBe('February Month');
    expect(spy).toHaveBeenCalled();
  });

});

el codigo fuente es o el codigo de la solución es:

(function(window) {
  
function GetMonthApi() {
  this.currentMonth = function () {
    return 'May';
  }
  this.nextMonth = function () {
    return 'June'
  }
}
function MonthCalculator() {
  this.api = new GetMonthApi();
  this.getNextMonth = function() {
    return this.api.nextMonth();
  }
  this.getCurrentMonth = function() {
    return this.api.currentMonth();
  }
}

  window.MonthCalculator = MonthCalculator;

})(window);

saludos!
en esta página web lo pueden verificar. esta super chido
https://embed.plnkr.co/plunk/eDY1ap

Hay errores en la redacción y en el código de este artículo. Por ejemplo cuando declaran:

const month = monthCalculator.currentMonth();

debería ser:

const month = monthCalculator.getCurrentMonth();