Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jasmine .and.throwError() is not caught by .catch in original code

I'm writing a test for a function, and have to trigger the .catch part of that function, but Jasmine's spiesfor some reason can't do that. Method to be tested:

foo(){
doStuff()
.catch((error) => {
    //stuff I still have to test
    bar()
})

}

doStuff() returns a Promise (hence the .catch-Setup), but for this test it's supposed to throw an error.

Here is my test:

it('tests the error handling of foo',(done) =>{
spyOn(object,'foo').and.throwError('Test Error');

object.foo();

expect(object.bar).toHaveBeenCalled();
done();

});

Is the way I'm approaching this wrong? Is that an error with Jasmine? (Google didn't find anything) [I stick to the (done) setup because almost all other tests are async and I want to keep the style]

[I cannot change the code to be tested]

like image 780
Hobbamok Avatar asked Mar 08 '18 12:03

Hobbamok


3 Answers

I think I had a problem similar to yours. Here's how I solved it

import { throwError } from 'rxjs';

it(`...`, fakeAsync(() => {
    spy = spyOn(authService, 'signIn').and.returnValue(throwError(loginError));
    /* do things */
    expectSnackbar('error', loginError);
    expect(authService.ensureLogin).toHaveBeenCalled(); 
}));

Here's how the call to the signIn method looks like:

return this.authService
    .signIn(payload.email, payload.password)
    .map((userId: string) => {
        // Whatever
    })
    .catch(error => {
        // Do something with the error
    });

And how the thrown error looks like inside signIn

public signIn(email: string, password: string): Observable<string> {
    return this.jsonServerService.get('login').pipe(
        map(users => {
            if (/* valid */) {
                return user.userId;
            } else {
                throw new Error('Error');
            }
        }),
    );
}
like image 59
Gaby Garro Avatar answered Nov 14 '22 10:11

Gaby Garro


If you call and.throwError(...); you throw the error within the test method.

You can try to return a Promise rejection instead:

spyOn(object, 'foo').and.rejectWith(new Error('Test Error'));

like image 34
Manuel Avatar answered Nov 14 '22 12:11

Manuel


and.throwError does not exist when I try it. Maybe I'm using an old version of jasmine.

I got it to work by returning a promise rejection:

and.returnValue(Promise.reject({response: {status: 401}}))
like image 1
whistling_marmot Avatar answered Nov 14 '22 11:11

whistling_marmot