Jasmine:期望在异步函数中抛出错误

Posted

技术标签:

【中文标题】Jasmine:期望在异步函数中抛出错误【英文标题】:Jasmine: Expecting Error to be Thrown in a Async Function 【发布时间】: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 哎呀!刚刚添加。抓得好! 【参考方案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' 这应该是答案!

以上是关于Jasmine:期望在异步函数中抛出错误的主要内容,如果未能解决你的问题,请参考以下文章

afterAll ReferenceError 中抛出错误:未定义模块,nodejs 中的 Karma/Jasmine 测试错误

不能从异步承诺执行器函数中抛出错误

期望函数在 Jest 中抛出异常

捕获回调函数引发的错误

错误:找不到模块 'jasmine-expect' [量角器]

setSinkId() 函数在 Electron App 中抛出错误