En este link explican spy0n de una manera mas facil https://scriptverse.academy/tutorials/jasmine-spyon.html
Bienvenida e Introducción
¿Qué son las pruebas unitarias?
¿Por qué hacer pruebas unitarias?
Creando un framework de pruebas básico
Mi primera prueba unitaria en JavaScript
Las funciones expect() y it()
Organizando el código para correr en la web
Organizando el código para correr utilizando nodejs
Análisis estático de código
Herramientas de análisis estático de código
ESLint: Agregando alertas a nuestro código con ECMA Script
Herramientas de corrección de estilo
Herramientas de tipado
Trabajando con Jasmine en el frontend
Profundización en SpyOn: Comandos más utilizados y cómo ponerlos a prueba
Configurar un ambiente de trabajo para trabajar con el framework jasmine
Configurar Jasmine utilizando Node.js
Primer set de pruebas con Jasmine
Diccionario Jasmine
Probando Nodejs apps con Jasmine
Introducción al módulo de testing del lado del servidor
Configurando el proyecto Jasmine utilizando npm
Agregando Plugins a Jasmine
Configurando nuestro reporter
Pruebas en el servidor: Verificando un status 200 en GET
Pruebas en el servidor: Probando el método GET y Reto con FindByID
Pruebas en el servidor: Probando el método POST (request to server)
Pruebas en el servidor: Probando el método POST (request to PDF)
Probando Angular apps con Jasmine
Tipos de pruebas
Pruebas en el frontend: Probando el componente principal (App)
Configurando los ciclos de vida
Creando las pruebas del formulario: Configuración
Creando las pruebas necesarias para un formulario. (Primeras pruebas)
Probando el caso de exito al guardar un elemento en el servidor.
Trabajando con event emitters
Testeando ngZone y navegación.
Configurando el TestBed de el componente PINs
Creando un espia sobre el objecto window
Pruebas de integración de Angular apps con Jasmine
Ejecutando funciones a través de eventos en el template
Probando la navegación
Probando servicios con HTTP
Completando las pruebas del servicio HTTP
Cierre del curso
Lectura
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.
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.
spyOn(obj, 'method') // obj.method es una función
const ref = spyOn(obj, 'method');
expect(ref).toHaveBeenCalled();
// O directamente
expect(obj.method).toHaveBeenCalled()
const ref = spyOn(obj, 'method');
expect(ref).toHaveBeenCalledWith('foo', 'bar');
// O directamente
expect(obj.method).toHaveBeenCalledWith('foo', 'bar')
expect(obj.method.callCount).toBe(2)
spyOn(obj, 'method').andCallThrough()
spyOn(obj, 'method').andReturn('value')
spyOn(obj, 'method').andCallFake(() => 'this is a function');
Aportes 14
Preguntas 0
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),
.
.
Código fuente: https://github.com/behagoras/jasmine-tests/tree/currentDate
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();
}
}
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();
¿Quieres ver más aportes, preguntas y respuestas de la comunidad? Crea una cuenta o inicia sesión.