首页 > 解决方案 > 在 setTimeout 之前和之后使用异步函数调用开玩笑

问题描述

我有一个主函数,它调用两个异步函数,中间有睡眠函数。这是一个基本示例:

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() 中的值增加到一天。并且还尝试在描述异步中创建函数。

标签: javascriptnode.jsasynchronoustestingjestjs

解决方案


我最近遇到了类似的问题,对我有用的是从异步调用中推进计时器。似乎 jest 不支持在承诺中设置计时器(请参阅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');
    });

  });
});

推荐阅读