Reputation: 557
I'm trying to start testing my component. The first thing that I wanted to test is if the ngOnInit
calls the correct services.
agreement.component.ts:
constructor(private agreementService: AgreementService,
private operatorService: OperatorService,
private accountService: AccountService,
private route: ActivatedRoute,
private router: Router,
private sessionService: SessionService,
private settingsService: SettingsService) {
this.agreementId = Number(this.route.snapshot.paramMap.get('agreementId'));
}
async ngOnInit() {
this.session = await this.sessionService.getSession();
this.settings = await this.settingsService.getSettings();
this.operatorService.getOperators(this.session.bic).subscribe(data => {
this.operators = data;
});
...
}
agreement.component.spec.ts
import {AgreementComponent} from './agreement.component';
import {async, TestBed} from '@angular/core/testing';
import {ActivatedRoute, convertToParamMap, Router} from '@angular/router';
import {RouterTestingModule} from '@angular/router/testing';
import {AgreementService} from '../../../services/agreement.service';
import {AccountService} from '../../../services/account.service';
import {SessionService} from '../../../services/session.service';
import {SettingsService} from '../../../services/settings.service';
describe('agreementComponent', () => {
let mockAgreementService: AgreementService;
let mockOperatorService;
let mockAccountService: AccountService;
let mockRoute: ActivatedRoute;
let mockRouter: Router;
let mockSessionService: SessionService;
let mockSettingsService: SettingsService;
let component: AgreementComponent;
beforeEach(async(() => {
mockAgreementService = jasmine.createSpyObj(['getAgreement']);
mockOperatorService = jasmine.createSpyObj(['getOperators']);
mockAccountService = jasmine.createSpyObj(['getFeeAccounts']);
mockRoute = jasmine.createSpyObj(['route']);
mockRouter = jasmine.createSpyObj(['router']);
mockSessionService = jasmine.createSpyObj(['getSession']);
mockSettingsService = jasmine.createSpyObj(['getSettings']);
TestBed.configureTestingModule({
declarations: [AgreementComponent],
imports: [
RouterTestingModule
],
providers: [
{
provide: ActivatedRoute, useValue:
{
snapshot: {
paramMap: convertToParamMap({agreementId: '0'})
}
}
},
]
});
component = new AgreementComponent(mockAgreementService, mockOperatorService, mockAccountService,
mockRoute, mockRouter, mockSessionService, mockSettingsService);
}));
it('should call operators service', () => {
component.ngOnInit();
expect(mockOperatorService).toHaveBeenCalled();
});
});
Currently I'm getting:
Failed: Cannot read property 'paramMap' of undefined
TypeError: Cannot read property 'ngOnInit' of undefined
I'm really sure this code lacks a lot of things in order to work fine, I just can't figure out what exactly is missing and what should be done differently, because googling my errors got me confused with ton of different solutions. I'm pretty new with angular testing so would like to have some pieces of advice how to write tests in the correct way.
Upvotes: 1
Views: 429
Reputation: 17514
Take a different approach by creating Stubs as explained in one of my articles.
export class MockOperatorService{
getOperators(){
return of({data: "someVal"})
}
}
and so on for other other services.
Use RouterTestingModule
as and when required in imports
Mock ActivatedRoute
and other services in as below:
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [AgreementComponent],
imports: [
RouterTestingModule
],
providers: [
{
provide: ActivatedRoute, useValue:
{
snapshot: {
paramMap: convertToParamMap({agreementId: '0'})
}
}
},
{provide: OperatorService , useClass: MockOperatorService},
{....similarly for AgreementService etc etc}
]
});
}));
beforeEach(() => {
fixture = TestBed.createComponent(AgreementComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
I realized that there is a lack of proper set of articles to learn about angular testing so I wrote collection of articles which you can find on the bottom of this page. I hope it'll help
To spy as asked in comment, you can do:
it('should call getOperators service in ngOnInit', () => {
spyOn(component.operatorService,"getOperators").and.callThrough();
component.ngOnInit();
expect(component.operatorService.getOperators).toHaveBeenCalled();
// you can also be more specific by using ".toHaveBeenCalledWith()"
});
Upvotes: 1