javascript - Error: Se esperaba que la función espía create hubiera sido llamada
Estoy escribiendo casos de prueba unitarios en Angular 7 para un componente con un servicio asíncrono y estoy obteniendo este error:
Error: Se esperaba que spy create hubiera sido llamado una vez. Se llamó 0 veces.
Aquí está mi componente:
export class RegistrationComponent implements OnInit {
submitRegistrationForm() {
if (this.profileForm.invalid) {
this.validateAllFields(this.profileForm);
} else {
// send a http request to save this data
this.guestUserService.create(this.profileForm.value).subscribe(
result => {
if (result) {
console.log('result', result);
this.router.navigate(['/login']);
}
},
error => {
console.log('error', error);
});
}
}
Caso de prueba unitario:
describe('RegistrationComponent', () => {
let component: RegistrationComponent;
let fixture: ComponentFixture<RegistrationComponent>;
let myService;
let mySpy;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [RegistrationComponent],
imports: [ ],
providers: [
{ provide: GuestUserService, useValue: new MyServiceStub() }]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(RegistrationComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should submit Registration Form', async(inject([Router], (router) => {
myService = TestBed.get(GuestUserService);
mySpy = spyOn(myService, 'create');
spyOn(router, 'navigate');
spyOn(component, 'submitRegistrationForm');
component.profileForm.controls['firstName'].setValue('Arjun');
component.profileForm.controls['lastName'].setValue('Singh');
component.profileForm.controls['password'].setValue('12345678');
component.profileForm.controls['confirmPassword'].setValue('12345678');
component.submitRegistrationForm();
expect(component.profileForm.invalid).toBe(false);
expect(component.submitRegistrationForm).toHaveBeenCalled();
expect(myService).toBeDefined();
expect(mySpy).toBeDefined();
expect(mySpy).toHaveBeenCalledTimes(1); // Getting error is this
expect(router.navigate).toHaveBeenCalled();
})
));
Intenté mover la declaración del espía a beforeEach, pero todavía da el mismo error.
¿Cómo solucionar este error?
¡Gracias!
Respuesta #1
Se esperaba que el espía 'create' hubiese sido llamado no es un error sino una prueba fallida.
Esto está sucediendo porque tampoco has usado callThrough(); en tu spyOn.
it('should submit Registration Form', async(inject([Router], (router) => {
myService = TestBed.get(GuestUserService);
mySpy = spyOn(myService, 'create').and.callThrough(); //callThrough()
spyOn(router, 'navigate');
spyOn(component, 'submitRegistrationForm').and.callThrough(); //callThrough()
component.submitRegistrationForm();
expect(component.profileForm.invalid).toBe(false);
expect(component.submitRegistrationForm).toHaveBeenCalled();
expect(myService).toBeDefined();
expect(mySpy).toBeDefined();
expect(mySpy).toHaveBeenCalledTimes(1);
expect(router.navigate).toHaveBeenCalled();
})
));
Respuesta #2
El spyOn te ayudará a configurar cómo debe reaccionar la función cuando se llame en tus pruebas. Básicamente, es la manera de Jasmine de crear mocks.
En tu caso, has definido lo que la prueba debe hacer cuando se llama a la función del servicio, que es callThrough. El problema es que también necesitas actuar sobre la función del servicio (o la función del alcance que llama a tu método de servicio) para activar el spyOn que hará callThrough.
it('load snapshot',function(){
//setup
spyOn(MyService, 'loadSomething').and.callThrough(); //statement 2
//act
//either call the scope function which uses the service
//$scope.yourServiceCallFunction();
//or call the service function directly
MyService.loadSomething(1); //this will callThrough
});
Aquí hay una prueba simple donde simularemos la respuesta del spyOn a una cadena
it('test loadSomething',function(){
//setup
spyOn(MyService, 'loadSomething').and.returnValue('Mocked');
//act
var val = MyService.loadSomething(1);
//check
expect(val).toEqual('Mocked');
});
