I'm trying to write a Unit test for my component in angular but when it calls an Api it getting undefine from reponse and i don't know how to handle this because it's my first time writing a unit test in angular please Help !!
This is my code for the Unit Test of the component UserProfile
import { ComponentFixture, TestBed,async } from '@angular/core/testing';
import { ApiService } from 'src/app/services/api.service';
import { UserProfileComponent } from './user-profile.component';
describe('UserProfileComponent', () => {
let component: UserProfileComponent;
let fixture: ComponentFixture<UserProfileComponent>;
let apiService: jasmine.SpyObj<ApiService>;
beforeEach(() => {
apiService = jasmine.createSpyObj('ApiService', ['getUser', 'getRepo']);
TestBed.configureTestingModule({
declarations: [UserProfileComponent],
providers: [{ provide: ApiService, useValue: apiService }],
});
fixture = TestBed.createComponent(UserProfileComponent);
component = fixture.componentInstance;
// Initialize test data
component.userDetail = { public_repos: 20 };
component.userName = 'testuser';
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
This is my UserProfile Component Code
import { Component, Input, OnInit } from '@angular/core';
import { ApiService } from 'src/app/services/api.service';
@Component({
selector: 'app-user-profile',
templateUrl: './user-profile.component.html',
styleUrls: ['./user-profile.component.scss'],
})
export class UserProfileComponent implements OnInit {
@Input() userDetail: any;
@Input() userName: any;
perPage: number;
pageNo: number;
isLoading: boolean;
repoList: any;
noOfPages: any[];
options: { value: number; label: number }[] = [];
constructor(private apiService: ApiService) {
this.perPage = 10;
this.pageNo = 1;
this.isLoading = false;
this.noOfPages = new Array(10);
for (let i = 10; i <= 100; i++) {
const tempObj = {
value: i,
label: i,
};
this.options.push(tempObj);
}
}
getUserRepos() {
this.isLoading = true;
this.apiService.getRepo(this.userName, this.perPage, this.pageNo).subscribe(
(data) => {
this.repoList = data;
setTimeout(() => {
this.isLoading = false;
}, 200);
},
(error) => {
error.log(error);
setTimeout(() => {
this.isLoading = false;
}, 200);
}
);
}
changePageNo(pageNo: number) {
this.pageNo =
pageNo <= 0
? 1
: pageNo > this.noOfPages.length
? this.noOfPages.length
: pageNo;
this.getUserRepos();
}
onPerPageNoChange() {
this.noOfPages = new Array(
Math.floor(this.userDetail.public_repos / this.perPage) + 1
);
this.pageNo = 1;
this.getUserRepos();
}
ngOnInit() {
this.noOfPages = new Array(
Math.floor(this.userDetail.public_repos / this.perPage) + 1
);
console.log(this.noOfPages)
this.getUserRepos();
}
}
code for getRepo method in Service
getRepo(githubUsername : string,perPage : number,pageNo : number){
return this.httpClient.get(`https://api.github.com/users/${githubUsername}/repos?per_page=${perPage}&page=${pageNo}`)
}
Reason for this is that you used
jasmine.createSpyObj
to create an objecet that will contain a spy for both agetUser
and agetRepo
method. By default these will not return anything butundefined
.You can change this by doing the following:
You can also put the line with
apiService.getRepo.and.returnValue(...)
inside each seperate test to change yourApiService
's behavior depending on the needs in each test scenario.