Mocking a service in unit tests

I am trying to mock a service for a component unit test.
Here my service:

@Injectable()
export class LoginService {

    constructor(public http: Http) { }

    getLanguages() {
        return this.http.get('the-url')
                        .map((res: Response) => res.json());
    }

NOTE: My component invokes this method in constructor (load the languages when construct the comp).

Then my attempt to mock it :

class MockLoginService {
    getLanguages() {
        return Observable.of(
            [
                {
                    'name': 'English (USA)',
                    'locale': 'en-US'
                },
                {
                    'name': 'Español',
                    'locale': 'es-US'
                }
            ]
        );
    }

And my component unit test:

  it('should load languages', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => {
        tcb
            .overrideProviders(LoginComponent, [ provide(LoginService, { useClass: MockLoginService })])
            .createAsync(LoginComponent).then((fixture) => {
                let element = fixture.nativeElement;
                let loginInstance = fixture.componentInstance;
                fixture.detectChanges();
                expect(loginInstance._loginService.getLanguages).toHaveBeenCalled();
                expect(element.querySelectorAll('option').length).toBe(5);
            });
    }));

Issue:

I see my mock service is called and data received is correct but my 2 tests are skipped! Here is the log :

angular2-polyfills.js:528 Unhandled Promise rejection: ‘expect’ was used when there was no current spec, this could be because an asynchronous test timed out ; Zone: ; Task: Promise.then ; Value: Error: ‘expect’ was used when there was no current spec, this could be because an asynchronous test timed out(…)

I undertand the service is executed async and the tests get lost somewhere.
angular2-polyfills.js:530 Error: Uncaught (in promise): Error: ‘expect’ was used when there was no current spec, this could be because an asynchronous test timed out(…)

I tried fakeAsync with tick – no success .
Thanks in advance !

1
Leave a Reply

avatar
1 Comment threads
0 Thread replies
0 Followers
 
Most reacted comment
Hottest comment thread
1 Comment authors
Jason Recent comment authors
  Subscribe  
newest oldest most voted
Notify of
Jason
Guest

You could try to instantiate your mocked service manually and set it within the beforeEachProviders method callback var service = new MockLoginService(); beforeEachProviders(() => [ provide(TestService, { useValue: service })]); it('should load languages', inject([TestComponentBuilder], (tcb: TestComponentBuilder) => { tcb .createAsync(LoginComponent).then((fixture) => { let element = fixture.nativeElement; let loginInstance = fixture.componentInstance; fixture.detectChanges(); expect(element.querySelectorAll('option').length).toBe(2); }); })); It works for me. See this plunkr: https://plnkr.co/edit/zTy3Ou?p=preview.