Reputation: 4998
I'm a beginner in Angular. I'm trying hard to learn Typescript and now I've been told to write unit test cases in Jasmine and Karma for every component
and service
I create. I've watched many tutorials to learn Unit testing in Angular. I'm an intern, yesterday I raised a Pull request on which my tech lead has given the following comment.
Here is the code that I've written.
filter-bar.component.ts
import { Component, OnInit, ViewChild, OnDestroy, Input, ChangeDetectorRef } from '@angular/core';
import './filter-bar.component.scss';
import { SisenseService } from '../services/sinsense.service';
import { SisenseConfigService } from '../services/sinsense-config.service';
import { Dashboard, Widget } from 'src/app/shared/models/sisenseConfig';
...
@Component({
selector: 'app-filter-bar',
templateUrl: './filter-bar.component.html'
})
export class FilterBarComponent implements OnInit, OnDestroy {
selectedMembersCount: number;
dataUnavailable: boolean;
constructor(
public sisenseService: SisenseService,
public sisenseConfigService: SisenseConfigService
) {}
ngOnInit() {
this.getDataFromWidget();
}
getDataFromWidget() {
this.sisenseService.getWidgetData(
this.sisenseConfigService.getDashboardId(Dashboard.POPULATION),
this.sisenseConfigService.getWidgetInfo(Dashboard.POPULATION, Widget.UNIQUE_LIVES).id,
widgetData => {
this.selectedMembersCount = widgetData.queryResult.value.data;
this.changeDetector.detectChanges();
},
() => {
this.dataUnavailable = true;
}
);
}
}
And this is the spec file that I've written:
filter-bar.component.spec.ts
import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { FilterBarComponent } from './filter-bar.component';
import { SisenseFilterService } from '../services/sinsense-filter.service';
import { PopUpService } from '@wuitk6/angular/components/popup/popup.service';
import { SisenseService } from '../services/sinsense.service';
import { SisenseConfigService } from '../services/sinsense-config.service';
describe('FilterPanelComponent', () => {
let component: FilterBarComponent;
let fixture: ComponentFixture<FilterBarComponent>;
mockSisenseConfigService.getWidgetInfo.and.returnValue({ id: 'demo_ID' });
fixture = TestBed.createComponent(FilterBarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
});
And here's the service, (i don't know who has written this code):
sisense-config.service.ts
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import 'rxjs/add/operator/do';
...
import { ErrorService } from './error.service';
// This is to avoid compile errors in typescript.
// The real variable will be added when sisense.js is loaded
declare var Sisense: any;
@Injectable({
providedIn: 'root'
})
export class SisenseConfigService {
constructor(private http: HttpClient, private errorService: ErrorService) {}
getDashboardId(dashboardName: string): string {
...
}
getWidgetInfo(dashboardName: string, widgetName: string): ISisenseWidget {
...
return widgetInfo;
}
}
I've written the test file but She is not OK with it. Please help me what exactly my tech lead is asking for. Feel free to ask for more code details.
Upvotes: 1
Views: 16991
Reputation: 17504
This would help you
describe('FilterPanelComponent', () => {
let component: FilterBarComponent;
let fixture: ComponentFixture<FilterBarComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
FilterBarComponent
],
imports: [],
providers: [
{
provide: SisenseService,
useClass: SisenseServiceStub
},
SisenseConfigService
]
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(FilterBarComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should call getDataFromWidget() on init method',()=>{
spyOn(component,'getDataFromWidget').and.callThrough();
component.ngOnInit();
expect(component.getDataFromWidget).toHaveBeenCalled()
})
it('getDataFromWidget should set selected member count',()=>{
component.selectedMembersCount = 0;
component.getDataFromWidget();
expect(component.selectedMembersCount).toEqual(1);
fixture.detectChanges();
const htmlEle = fixture.debugElement.nativeElement.querySelector('#some-count'); // For class try query(By.css('.some-count')).nativeElement;
expect(htmlEle.innerHTML).toBe(1);
})
});
// this is the stub she is talking about
export class SisenseServiceStub{
getWidgetData(){
return of({
queryResult : {
value : {
data : 1
}
}
})
}
}
Few months back, I also saw some of my juniors struggling with unit tests. So, I wrote series of articles which can help you as well.
Give it a try and let me know if it helped. Here is how you play with stubs and spies
Upvotes: 1