【问题标题】:Jasmine: Expecting Error to be Thrown in a Async FunctionJasmine:期望在异步函数中抛出错误
【发布时间】:2017-12-06 04:12:48
【问题描述】:

我的 angular2 应用程序中有一个异步函数,我想为其编写单元测试。想象一下我的功能是这样的:

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();
}

现在,我正在考虑检查 if 条件。我尝试了以下代码;但是,这个测试总是失败,因为我的代码实际上并不等待任何结果:

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

我不知道应该如何为这些类型的逻辑编写单元测试...

【问题讨论】:

  • 你不应该将 1 传递给你的函数吗? myService.myFunc(1);
  • @ppham27 哎呀!刚刚添加。抓得好!

标签: angular unit-testing typescript jasmine angular2-services


【解决方案1】:

您可以使用 spy 断言方法是否抛出错误:

import Spy = jasmine.Spy;
it('should...', () => {
 (mySerivce.myFunc as Spy).and.Callthrough();
 mySerivce.myFunc(1);
 expect(mySerivce.myFunc).toThrow();
});

可选择使用fakeASync 来解决“racecondition”问题。

希望对你有帮助。

【讨论】:

  • 我假设您的意思是写“它”而不是第一个“除外”。不过,您的方法似乎无法解决我的问题。当函数完全运行时调用 myService.myFunc().then。就我而言,它将引发异常。因此,它永远不会进入 then 块,因为“在默认 jasmine 超时内未调用异步回调函数”或类似的东西。
  • 您在哪里调用了 myFunc(1)
  • 我认为这是暗示的。我的坏:)
【解决方案2】:

你可以使用try catch。

这是我想出的,也是 Github 茉莉花问题跟踪器上建议的。

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)

    })
});

我也给自己写了个小帮手

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)
    });
});

【讨论】:

    【解决方案3】:

    现在 jasmine (3.3+) 原生支持此功能:

    https://jasmine.github.io/api/3.4/async-matchers.html

    it('should...', async () => {
      await expectAsync(myService.myFunc(1))
        .toBeRejectedWith(new Error('a should not be 1'));
    });
    

    【讨论】:

    • 我认为这是最好的方法。它对我很有效,而且非常清晰!
    • 我喜欢这个答案,但是它似乎对我不起作用。我正在测试一个返回新承诺的函数。在 promise 内部是它在解决或拒绝命中之前抛出错误的地方。有任何想法吗?错误会出现'Type Error ../filenameHere.ts'
    • 这应该是答案!
    猜你喜欢
    • 2023-02-08
    • 2020-05-01
    • 1970-01-01
    • 2017-03-24
    • 1970-01-01
    • 2012-05-01
    • 2011-05-07
    • 2017-10-23
    • 2019-08-16
    相关资源
    最近更新 更多