Estoy escribiendo una prueba unitaria para la aplicación angular, estoy probando si la función de servicio devuelve un valor.
componente.spec.ts
import {TopToolBarService} from '../../top-toolbar/top-toolbar.service'; beforeEach(async(() => { TestBed.configureTestingModule ({ declarations: [ UsersListComponent], providers: [TopToolBarService],//tried mocking service here,still test failed schemas:[CUSTOM_ELEMENTS_SCHEMA] }) .compileComponents(); })); beforeEach(() => { fixture = TestBed.createComponent(UserListComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should return data from service function', async(() => { let mockTopToolBarService: jasmine.SpyObj<TopToolBarService>; mockTopToolBarService = jasmine.createSpyObj('TopToolBarService', ['getCustomer']); mockTopToolBarService.getCustomer.and.returnValue("king"); fixture.detectChanges(); expect(component.bDefine).toBe(true); //fails }))componente.ts
bDefine = false; ngOnInit() { let customer = this.topToolBarService.getCustomer(); if (customer == null) { bDefine = false; } else { bDefine = true; } }Creo que me he burlado de la función de servicio en mi prueba, por lo que espero que haya llegado a otra parte donde la variable se establece en 'verdadero'.
TopToolBarService.ts
import { EventEmitter, Injectable, Output } from "@angular/core"; @Injectable() export class TopToolBarService { customer = null; getCustomer() { return this.customer; } }La respuesta de @Pedro Bezanilla es suficientemente buena. Solo aquí hay otra forma con menos código, dado que el servicio es un singleton, que creo que es la mayor parte del caso.
La diferencia es que no se proporciona ninguna configuración de proveedor para configureTestingModule . spyOn configura el espía contra el objeto de servicio tomado de TestBed.
Llamar TestBed.inject en lugar de TestBed.get se debe a que está en desuso desde la versión 9.0.0.
Para los servicios singleton , aquí hay un documento en el sitio web de Angular y, para completarlo, tenga en cuenta este problema de GitHub .
describe('Component TEST', () => { ... let mockToolBarService: TopToolBarService; ... beforeEach(waitForAsync(() => { TestBed.configureTestingModule({ declarations: [ UsersListComponent ], schemas:[ CUSTOM_ELEMENTS_SCHEMA ] }); mockTopToolBarService = TestBed.inject(TopToolBarService); spyOn(mockTopToolBarService, 'getCustomer').and.returnValue(of([])); })); ...Puede considerar el uso de ng-mocks para evitar todo ese repetitivo para configurar TestBed .
beforeEach(() => MockBuilder(UsersListComponent) .mock(TopToolBarService, { // adding custom behavior to the service getCustomer: jasmine.createSpy().and.returnValue('king'), }) ); it('should return data from service function', () => { const fixture = MockRender(UsersListComponent); // now right after the render the property should be true expect(fixtur.point.componentInstance.bDefine).toBe(true); }));Cambia el valor de tu proveedor
beforeEach(() => { TestBed.configureTestingModule({ declarations: [ UsersListComponent], providers: [{ provide: TopToolBarService, useValue: jasmine.createSpyObj('TopToolBarService', ['getCustomer']) }], schemas:[CUSTOM_ELEMENTS_SCHEMA] }); mockTopToolBarService = TestBed.get(TopToolBarService); mockTopToolBarService.getCustomer.and.returnValue(of([])); // mock output of function })Debe configurar el módulo de prueba antes de ejecutar su código. No conoce su objeto espía a menos que lo pase a TestBed.configureTestingModule como una importación.
https://angular.io/guide/testing#component-with-a-dependency
Intente actualizar los proveedores dentro de beforeEach (async (() => ...) y mueva su variable de servicio simulado en la parte superior:
describe('Component TEST', () => { ... let mockToolBarService; ... beforeEach(async(() => { ... mockToolBarService = jasmine.createSpyObj(['getCustomer']); mockToolBarService.getCustomer.and.returnValue('king'); TestBed.configureTestingModule ({ ... providers: [ { provide: TopToolBarService, useValue: mockToolBarService } ] ...¡Espero eso ayude!