Reputation: 2719
I am writing unit test for angular app, I am testing if the service function returns a value.
component.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
}))
component.ts
bDefine = false;
ngOnInit() {
let customer = this.topToolBarService.getCustomer();
if (customer == null) {
bDefine = false;
} else {
bDefine = true;
}
}
I believe I have mocked the service function in my test, so I expect it must have reached else part where variable is set to 'true'.
TopToolBarService.ts
import { EventEmitter, Injectable, Output } from "@angular/core";
@Injectable()
export class TopToolBarService {
customer = null;
getCustomer() {
return this.customer;
}
}
Upvotes: 52
Views: 166871
Reputation: 1
Hi please try this.
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
import { AppService } from './app.service';
import { of } from 'rxjs/internal/observable/of';
describe('AppComponent', () => {
beforeEach( () => {
TestBed.configureTestingModule({
imports: [AppComponent],
providers: [AppService],
}).compileComponents();
});
it('should render with mocked title', () => {
const fixture = TestBed.createComponent(AppComponent);
const service = fixture.debugElement.injector.get(AppService);
let mockData = {
id: 1,
title: 'Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptop',
price: 109.95,
description:
'Your perfect pack for everyday use and walks in the forest. Stash your laptop (up to 15 inches) in the padded sleeve, your everyday',
category: "women's clothing",
image: 'https://fakestoreapi.com/img/81fPKd-2AYL._AC_SL1500_.jpg',
rating: { rate: 3.9, count: 120 },
};
spyOn(service, 'getData').and.returnValue(of(mockData));
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, Fjallraven - Foldsack No. 1 Backpack, Fits 15 Laptop');
});
});
for more details please visit my blog
Upvotes: -1
Reputation: 1365
Try updating providers inside beforeEach(async(() => ...)
and moving your mockedService
variable on the top of it:
describe('Component TEST', () => {
...
let mockToolBarService;
...
beforeEach(async(() => {
...
mockToolBarService = jasmine.createSpyObj(['getCustomer']);
mockToolBarService.getCustomer.and.returnValue('king');
TestBed.configureTestingModule ({
...
providers: [ { provide: TopToolBarService, useValue: mockToolBarService } ]
...
Hope it helps!
Upvotes: 47
Reputation: 13539
You might consider usage of ng-mocks to avoid all that boilerplate to configure 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);
}));
Upvotes: 3
Reputation: 1778
Change your provider value
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
})
Upvotes: 21
Reputation: 466
You have to configure the testing module before you run your code. It doesn't know about your spy object unless you pass it to the TestBed.configureTestingModule
as an import.
https://angular.io/guide/testing#component-with-a-dependency
Upvotes: 1