A method of a service that I am using in my component has a callback as the second argument. When This callback is executed it returns a value which is assigned to a variable in the component.
I want to mock the method in my service for unit testing and assert in the unit test that the service method was able to update the variable of my component.
export class AppComponent {
title = 'sample-app';
sampleValue: string = '';
constructor(private dataService:DataService)
{}
getSampleValue()
{
this.dataService.fetchData('Sample Value',(response) => {
this.sampleValue = response;
});
}
}
export class DataService {
constructor() {}
fetchData(inputData:string,callback:(outputData:string)=>void) {
const output:string = inputData + ' from service';
callback(output);
}
}
describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let mockDataService:jasmine.SpyObj<DataService>;
beforeEach(() => {
mockDataService = jasmine.createSpyObj('DataService', ['fetchData']);
TestBed.configureTestingModule({
imports: [RouterTestingModule],
declarations: [AppComponent],
providers: [{
provide: DataService,
useValue: mockDataService
}]
});
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
});
it(`should set sample value as 'Sample Value from service'`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
mockDataService.fetchData('Sample Value', (response) => {
app.sampleValue = response;
})
expect(app.sampleValue).toEqual('Sample Value from service');
});
});
You can use callFake
method of jasmine, to define the method of the fetchData
.
You are also missing compileComponents
method execution on TestBed.configureTestingModule
.
I am assuming, you have an API call on the service, so you can use fakeAsync
and flush
to wait for the API call to complete before running the test.
import { TestBed, ComponentFixture, waitForAsync, fakeAsync, flush } from '@angular/core/testing';
import { AppComponent, DataService } from './app.component';
describe('AppComponent', () => {
let component: AppComponent;
let fixture: ComponentFixture<AppComponent>;
let mockDataService: jasmine.SpyObj<DataService>;
beforeEach(() => {
mockDataService = jasmine.createSpyObj('DataService', ['fetchData']);
TestBed.configureTestingModule({
imports: [],
declarations: [AppComponent],
providers: [
{
provide: DataService,
useValue: mockDataService,
},
],
}).compileComponents();
});
beforeEach(waitForAsync(() => {
fixture = TestBed.createComponent(AppComponent);
component = fixture.componentInstance;
fixture.detectChanges();
}));
it(`should set sample value as 'Sample Value from service'`, fakeAsync(() => {
const app = fixture.componentInstance;
mockDataService.fetchData.and.callFake((inputData: string, callback: (outputData: string) => void) {
const output: string = inputData + ' from service';
callback(output);
});
app.getSampleValue();
flush();
expect(app.sampleValue).toEqual('Sample Value from service');
}));
});