Jasmine: Expecting Error to be Thrown in a Async Function

Viewed 9902

I have an async function in my angular2 app for which I want to write a unit test. Imagine my function is like this:

myFunc(a: int): Promise<void> {
    if (a == 1)
        throw new Error('a should not be 1');

    let body = {
        value: a
    };
    return apiService.patch('/url/', JSON.stringify(body)).toPromise();
}

Now, I'm thinking of checking that if condition. I tried the following code; but, this test always fails since my code actually does not wait for any results:

it('should throw error if a = 1', () => {
    expect(() => {
        mySerivce.myFunc(1);
    }).toThrow(new Error('a should not be 1'));
})

I don't know how I should write unit tests for these types of logics...

3 Answers

You can use try catch.

This is what I came up with and it was also what was suggested on the Github issue tracker for jasmine.

https://github.com/jasmine/jasmine/issues/1410

function double(a: number): Promise<number> {
   if (a === 1) {
       throw new Error('a should not be 1')
   }

   return new Promise(function (resolve, reject) {
       setTimeout(resolve, 100, a * 2 )
   })
}

describe('test double', () => {
    it('should double any number but 1', async() => {
        const result = await double(2);
        expect(result).toBe(4)
    });

    it('should throw an error', async() => {
        let error;
        try {
            await double(1)
        } catch (e) {
            error = e;
        }
        const expectedError = new Error('a should not be 1');
        expect(error).toEqual(expectedError)

    })
});

I also wrote myself a little helper

async function unpackErrorForAsyncFunction(functionToTest: Function, ...otherArgs: any[]): Promise<Error> {
    let error;
    try {
        const result = await functionToTest(...otherArgs);
    } catch (e) {
        error = e;
    }
    return error;
}

function double(a: number): Promise<number> {
    if (a === 1) {
        throw new Error('a should not be 1')
    }

    return new Promise(function (resolve, reject) {
        setTimeout(resolve, 100, a * 2 )
    })
}

function times(a: number, b: number): Promise<number> {
    if (a === 1 && b === 2) {
        throw new Error('a should not be 1 and 2')
    }

    return new Promise(function (resolve, reject) {
        setTimeout(resolve, 100, a * b )
    })
}

describe('test times and double with helper', () => {
    it('double should throw an error with test helper', async() => {
        const result = await unpackErrorForAsyncFunction(double, 1);
        const expectedError = new Error('a should not be 1');

        expect(result).toEqual(expectedError)
    });

    it('times should throw an error with test helper', async() => {
        const result = await unpackErrorForAsyncFunction(times, 1, 2);
        const expectedError = new Error('a should not be 1 and 2');

        expect(result).toEqual(expectedError)
    });
});
Related