1

I have a service that is calling a http function:

processLogin(info) {
    return this._call.post('login', info).subscribe(response => {
        if (response.status === 'success') {
            this._auth.login(response.object);
            return true;
        }

        return false;
    }, error => {
        return false;
    });
}

And this is the test I'm trying to make:

describe('Facebook Login', () => {
    let service: FacebookLoginService;
    let call: CallService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
                FacebookLoginService,
                { provide: CallService, useClass: CallServiceMock },
            ]
        });

        service = TestBed.get(FacebookLoginService);
        call = TestBed.get(CallService);
    });

    it('should process the login when the post method return success', () => {
        spyOn(call, 'post').and.returnValue(Observable.of({status: 'success'}));

        service.processLogin('any').subscribe(response => {
            console.log(response);
        });
    });
});

However, when I run the test I keep getting the error message

processLogin().subscribe( ... ) is not a function

And if I change the type of response mocked to anything but Observable.of, I get the error message

call.post.subscribe( ... ) is not a function

Why is it not wokirng? I have a very similar test on another service that also calls call.post() and it's working.

0

1 Answer 1

1

processLogin returns not an observable but a subscription, so there will be no subscribe method on it. Returned values in subscribe callbacks are ignored, so processLogin won't work as expected.

It likely should be changed to return an observable instead:

return this._call.post('login', info).map(response => { ... });

Then it can be tested like:

spyOn(_call, 'post').and.returnValue(Observable.of({ status: 'success' }));

const login$ = service.processLogin('any');
expect(_call).toHaveBeenCalledWith('login', 'any');

login$.subscribe(response => {
  expect(response).toBe(...);
}, err => { throw err });

It will also need to mock _auth.

Sign up to request clarification or add additional context in comments.

5 Comments

With those changes the test now has the subscribe method, but the actual processLogin method never execute. I think it's because it's missing the subscribe().
It's subscribed with login$.subscribe in test. If you mean that it doesn't work as expected in the app, then yes, you need add subscribe wherever you use it.
I just don't understand how to make it work. Because if I don't use .subscribe() the method never execute. But if I do, then the test is going to fail, as you explained in the answer. What changes should I made to the method in order to keep both working?
You need to replace subscribe word in processLogin method with map word. Then you need to make sure that you added subscribe(...) to every place where you use processLogin in your app, because it is cold observable.
Oh.. Ok. I was thinking that it has anything to do with the own method. I get it. Now it's working. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.