簡體   English   中英

在 setTimeout 之前和之后使用異步 function 調用開玩笑

[英]Jest with async function calls before and after setTimeout

我有一個主 function 調用兩個異步函數,兩者之間有睡眠 function。 這是一個基本示例:

index.js

const func1 = async() => {
    setTimeout(()=>{console.log('func 1...')}, 1000);
}

const func2 = async() => {
    setTimeout(()=>{console.log('func 2...')}, 1000);
}

const sleep = ms => {
    console.log(`Sleeping for ${ms/1000} seconds`);
    return new Promise(resolve => {
        setTimeout(resolve, ms);
    })
}

const main = async() => {
    try {
    await func1();
    // Sleeping for a long long time
    console.log('Before Sleep');
    await sleep(2000000);
    console.log('After Sleep')
    await func2();
    return 'success';
    } catch(err) {
        console.log(err);
        return 'error'
    }
}

這是我的測試代碼:

index.test.js

const index = require('./index');

jest.useFakeTimers();

describe('Testing index.js...', () => {
    test('Should return success', async() => {
        const promise = index();
        jest.advanceTimersByTime(2000000);
        promise.then(response => {
            expect(response).toBe('success');
        }) 
    });
})

測試通過,但控制台顯示以下內容:

func 1...
Before Sleep
Sleeping for 2000 seconds

我嘗試了同樣的方法,但是 func1() 和 func2() 是同步函數:

const func1 = () => {
    console.log('func 1...');
}

const func2 = () => {
    console.log('func 2...');

}

const sleep = ms => {
    // Sleeping for a long time
    console.log(`Sleeping for ${ms/1000} seconds`);
    return new Promise(resolve => {
        setTimeout(resolve, ms);
    })
}

const main = async() => {
    try {
    func1();
    // Sleeping for a long long time
    console.log('Before Sleep');
    await sleep(2000000);
    console.log('After Sleep')
    func2();
    return 'success';
    } catch(err) {
        console.log(err);
        return 'error'
    }
}

在這種情況下,測試通過並且日志也符合預期:

func 1...
Before Sleep
Sleeping for 2000 seconds
After Sleep
func 2...

在相同的同步代碼中,如果我使 func1 異步(保持 func2 同步),問題會再次出現。 如果 func1 是同步的,而 func2 是異步的,那么一切都會按預期進行。

我也嘗試過使用 jest.runAllTimers() 和 jest.runOnlyPendingTimers()。 我也嘗試在測試文件中使用 async-await ,但是(可以理解)給出了超時錯誤:

index.test.js使用異步等待

const index = require('./index');

jest.useFakeTimers();

describe('Testing index.js...', () => {
    test('Should return success', async() => {
        const promise = index();
        jest.advanceTimersByTime(3000000);
        const response = await promise;
        expect(response).toBe('success');  
    });
})

控制台

func 1...
Before Sleep
Sleeping for 2000 seconds

錯誤

Timeout - Async callback was not invoked within the 5000ms timeout specified by jest.setTimeout.Timeout

我怎樣才能使這項工作? 我開玩笑地嘗試了很多 Github 問題的解決方案,還有很多關於堆棧溢出的問題,但似乎沒有一個解決方案有效。

我正在使用 jest 25.5.4

編輯:我還嘗試將 jest.advanceTimersBytTime() 中的值增加到一天。 並且還嘗試在描述異步中制作 function。

我最近遇到了類似的問題,對我有用的是從異步調用中推進計時器。 似乎 jest 不支持在 promise 中設置計時器(參見https://github.com/facebook/jest/pull/5171#issuecomment-528752754 )。 嘗試做:

describe('Testing index.js...', () => {
  it('Should return success', () => {    
    const promise = main();
    Promise.resolve().then(() => jest.advanceTimersByTime(2000005));
    return promise.then((res) => {
      expect(res).toBe('success');
    });

  });
});

async , raw promises 和done回調不應該在測試中一起使用。 這是開發人員對 Jest 異步測試並不完全滿意的一個常見跡象,這會導致測試容易出錯。

original 的問題是promise.then(...) promise 被忽略,因為它沒有被鏈接。 異步測試應返回 promise 以便將其鏈接。

func1func2返回立即解決並產生一個滴答聲延遲而不是 1 秒延遲的承諾。 應該考慮到這一點,因為否則會出現在advanceTimersByTime之后調用setTimeout的競爭條件。

它應該是:

test('Should return success', async() => {
    const promise = index();
    await null; // match delay from await func1() 
    jest.advanceTimersByTime(2000000);
    const response = await promise;
    expect(response).toBe('success');
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM