Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to spy on methods of service when the service is provided in the root of Component

I am writing unit test for a angular component using karma-jasmine. I have used providers in my ProfileComponent and injected ProfileService.

profile.component.ts

@Component({
    selector: 'app-profile',
    templateUrl: './profile.component.html',
    styleUrls: ['./profile.component.scss'],
    providers: [ProfileService]
})
export class ProfileComponent implements OnInit {

    public data;

    constructor(private profileService: ProfileService) {}

    ngOnInit() {
        await this.profileService.login();
        this.profileService.getData('A').subscribe((result) => {
            this.data = result;
        });
    }

}

profile.service.ts

@Injectable()
export class ProfileService {

    private baseUrl: string;

    constructor(private http: HttpClient) {
        this.baseUrl = 'https://localhost:4002';
    }

    public async login() {
        const loginUrl = `${this.baseUrl}/api/Login`;
        return this.http.post(loginUrl, {}, { headers }).toPromise();
    }

    getData(id: string) {
        const url = `${this.baseUrl}/api/GetData/${id}`;
        return this.http.get(url, { headers });
    }
}

profile.component.spec.ts

const data = ['A', 'B', 'C'];

describe('Client.App.ProfileComponent', () => {
    let component: ProfileComponent;
    let fixture: ComponentFixture < ProfileComponent > ;
    let profileService: ProfileService;
    let profileData;

    beforeEach(async (() => {
        TestBed.configureTestingModule({
            imports: [HttpClientTestingModule, ReactiveFormsModule, RouterTestingModule],
            declarations: [ProfileComponent],
            providers: [ProfileService],
            schemas: [NO_ERRORS_SCHEMA]
        }).compileComponents();
    }));

    beforeEach(fakeAsync(() => {
        profileData = new Subject();
        profileService = TestBed.inject < ProfileService > (ProfileService);
        spyOn(profileService, 'login').and.returnValue({});
        spyOn(profileService, 'getData').and.returnValue(profileData);
        fixture = TestBed.createComponent(ProfileComponent);
        component = fixture.componentInstance;
        fixture.detectChanges();
    }));

    it('shall create the component', () => {
        profileData.next(data);
        fixture.detectChanges();
        expect(component).toBeDefined();
    });
});

I added a debugger and checked that its failing in login. So, I have two questions:

  1. As I have used providers in the Profile Component, can I inject the ProfileService in the profile.component.spec.ts file as it will create two instance of the same service?
  2. How to spy on login() and getData() of ProfileService as below statement is not working...?
spyOn(profileService, 'login').and.returnValue({});

Please help me on this.

like image 292
Asif Zaidi Avatar asked Sep 17 '25 12:09

Asif Zaidi


1 Answers

  1. As I have used providers in the Profile Component, can I inject the Profileervice in the profile.component.spec.ts file as it will create two instance of the same service..??

Answer: You should create a Stub for the service to replace dependency on actual ProfileService using useClass

export class ProfileServiceStub {
    getData(id: string) {
       return of({some_obj: "value"})
    }
}

and in spec.ts

    beforeEach(async(() => {
        TestBed.configureTestingModule({
            imports: [HttpClientTestingModule, ReactiveFormsModule, RouterTestingModule],
            declarations: [ProfileComponent],
            providers: [ {provide: ProfileService , useClass: ProfileServiceStub } ], // <-- useclass here
            schemas: [NO_ERRORS_SCHEMA]
        }).compileComponents();
  1. How to spy on login() and getData() of ProfileService as below statement is not working...?

Answer: Make the service public in component constructor as below:

constructor(public profileService: ProfileService) { }

I would strongly recommend you to read my article on something similar where I have tested the component

like image 139
Shashank Vivek Avatar answered Sep 20 '25 03:09

Shashank Vivek