Ensure the service is made public in the component constructor for improved testing capabilities
Adopt the following example as a standard practice:
service.ts
@Injectable({
providedIn: 'root',
})
export class UserSvcService {
test() {
return of('test');
}
}
for a component.ts
@Component({
selector: 'app-user-detail',
templateUrl: './user-detail.component.html',
styleUrls: ['./user-detail.component.scss'],
})
export class UserDetailComponent implements OnInit {
name = 'test';
val :string
public constructor(public _userSvc: UserSvcService) {}
ngOnInit() {
this._userSvc[this.name]().subscribe(res =>
this.val = res
);
}
}
Create a stub like this:
export class UserServiceStub {
test() {
return of('test mock');
}
}
replace the actual service with stub as:
describe('UserDetailComponent', () => {
let component: UserDetailComponent;
let fixture: ComponentFixture<UserDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [],
declarations: [UserDetailComponent],
providers: [{ provide: UserSvcService, useClass: UserServiceStub }],
}).compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(UserDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
expect(component.val).toBe('test mock'); // move into another "it" block
});
This setup should function correctly. To enable smooth testing, remember to utilize `spyOn` with the service marked as `public` first:
it('should ', () => {
spyOn(component.testService,'getData').and.returnValue(return of({some val}));
component.loadData();
expect(component.testService.getData).toHaveBeenCalled();
});
Take a look at this article for more insights