在调用beforeEach()之前,异步beforeAll()不会完成 [英] Async beforeAll() does not finish before beforeEach() is called

查看:80
本文介绍了在调用beforeEach()之前,异步beforeAll()不会完成的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在Jest中, beforeAll()应该在 beforeEach()之前运行.

问题是,当我对 beforeAll()使用异步回调时,Jest在继续进行 beforeEach()之前不会等待回调完成.

如何强制Jest在继续进行 beforeEach()之前等待异步 beforeAll()回调完成?

最小的可复制示例

tests/myTest.test.js

  const connectToMongo = require('../my_async_callback')//这使用异步回调.beforeAll(connectToMongo)//这是在beforeAll块完成之前输入的.=,(beforeEach(()=> {console.log('beforeEach的输入主体')}test('t1'),()=>{Expect(1).toBe(1)}test('t2'),()=>{Expect(2 + 2).toBe(4)}test('t3'),()=>{期望(3 + 3 + 3).toBe(9)} 

my_async_callback.js

  const connectToMongo = async()=>{尝试 {等待mongoose.connect(config.MONGODB_URI,{useNewUrlParser:是的,useUnifiedTopology:是的,useFindAndModify:false,useCreateIndex:true})console.log('已连接到MongoDB')} catch(err){console.log(`连接到MongoDB时出错:$ {err.message}`)}}module.exports = connectToMongo 

更新:正如公认的答案所指出的那样,Jest实际上确实先等待 beforeAll 完成,除非Promise链断裂或超时.因此,我的问题的前提是错误的.我的 connectToMongo 函数正在超时,只需增加Jest超时即可解决此问题.

解决方案

问题是,当我对 beforeAll()使用异步回调时,Jest在继续进行 beforeEach()之前不会等待回调完成.

如何强制Jest在继续进行 beforeEach()之前等待异步 beforeAll()回调完成?

TLDR

简短的答案是,Jest 确实会先等待异步 beforeAll()回调完成,然后再继续进行 beforeEach().>

这意味着,如果 beforeEach()在应在 beforeAll()中运行的内容之前运行,则Promise链必须断开或 beforeAll 功能超时.


玩笑中的队列运行器

所有 beforeAll beforeEach test afterEach afterAll 与测试关联的功能收集在 queueableFns 中,并链接为


破碎的承诺链

如果 beforeEach 在应在 beforeAll 中运行的内容之前运行,则Promise链可能已损坏:

  const order = [];//不返回Promise,并且会中断Promise链const func =()=>{setTimeout(()=> {order.push(2);},1000);}const asyncFunc = async()=>{order.push(1);等待func();//实际上并不等待2被推送order.push(3);}beforeAll(asyncFunc);beforeEach(()=> {order.push(4);});它(应按顺序运行",()=> {Expect(order).toEqual([1,2,3,4]);//失败:[1、3、4]}); 


超时

...或者有超时(请注意,超时将由Jest在输出中报告):

  const order = [];jest.setTimeout(100);//100ms超时const asyncFunc = async()=>{order.push(1);等待新的Promise(resolve => {setTimeout(resolve,1000);});//超时order.push(2);}beforeAll(asyncFunc);beforeEach(()=> {order.push(3);});它(应按顺序运行",()=> {Expect(order).toEqual([1,2,3]);//失败:[1,3]和超时错误}); 

In Jest, beforeAll() is supposed to run before beforeEach().

The problem is that when I use an async callback for beforeAll(), Jest doesn't wait for the callback to finish before going on to beforeEach().

How can I force Jest to wait for an async beforeAll() callback to finish before proceeding to beforeEach()?

Minimal reproducible example

tests/myTest.test.js

const connectToMongo = require('../my_async_callback')    

// This uses an async callback.
beforeAll(connectToMongo) 

// This is entered before the beforeAll block finishes. =,(
beforeEach(() => { 
  console.log('entered body of beforeEach')  
}

test('t1'), () => {
  expect(1).toBe(1)
}
test('t2'), () => {
  expect(2+2).toBe(4)
}
test('t3'), () => {
  expect(3+3+3).toBe(9)
}

my_async_callback.js

const connectToMongo = async () => {
  try {
    await mongoose.connect(config.MONGODB_URI, { 
      useNewUrlParser: true, 
      useUnifiedTopology: true, 
      useFindAndModify: false, 
      useCreateIndex: true 
    })
    console.log('Connected to MongoDB')
  } catch (err) {
    console.log(`Error connecting to MongoDB: ${err.message}`)
  }
}

module.exports = connectToMongo

UPDATE: As the accepted answer helpfully points out, Jest actually does wait for beforeAll to finish first, except in the case of a broken Promise chain or a timeout. So, the premise of my question is false. My connectToMongo function was timing out, and simply increasing the Jest timeout solved the problem.

解决方案

The problem is that when I use an async callback for beforeAll(), Jest doesn't wait for the callback to finish before going on to beforeEach().

How can I force Jest to wait for an async beforeAll() callback to finish before proceeding to beforeEach()?

TLDR

The short answer is that Jest does wait for an async beforeAll() callback to finish before proceeding to beforeEach().

This means that if beforeEach() is running before something that should run in beforeAll() then the Promise chain must be broken or the beforeAll function is timing out.


Queue Runner in Jest

All of the beforeAll, beforeEach, test, afterEach, afterAll functions associated with a test are collected in queueableFns and are chained on these lines in queueRunner.ts:

  const result = options.queueableFns.reduce(
    (promise, fn) => promise.then(() => mapper(fn)),
    Promise.resolve(),
  );

So Jest starts with a resolved Promise and chains every function, in order, to the Promise chain with .then.


This behavior can be seen with the following test:

const order = [];

// first beforeAll with async function
beforeAll(async () => {
  order.push(1);
  await new Promise((resolve) => { setTimeout(resolve, 1000); });
  order.push(2);
});

// first beforeEach with done callback
beforeEach(done => {
  order.push(4);
  setTimeout(() => {
    order.push(6);
    done();
  }, 1000);
  order.push(5);
});

// second beforeEach
beforeEach(() => {
  order.push(7);
});

// second beforeAll
beforeAll(() => {
  order.push(3);
});

it("should run in order", () => {
  expect(order).toEqual([1, 2, 3, 4, 5, 6, 7]);  // SUCCESS!
});


Broken Promise Chain

If beforeEach is running before something that should run in beforeAll then it is possible the Promise chain is broken:

const order = [];

// does not return Promise and will break the Promise chain
const func = () => {
  setTimeout(() => { order.push(2); }, 1000);
}

const asyncFunc = async () => {
  order.push(1);
  await func();  // doesn't actually wait for 2 to be pushed
  order.push(3);
}

beforeAll(asyncFunc);

beforeEach(() => {
  order.push(4);
});

it("should run in order", () => {
  expect(order).toEqual([1, 2, 3, 4]);  // FAIL: [1, 3, 4]
});


Timeout

...or there is a timeout (note that the timeout will be reported by Jest in the output):

const order = [];

jest.setTimeout(100);  // 100ms timeout

const asyncFunc = async () => {
  order.push(1);
  await new Promise(resolve => { setTimeout(resolve, 1000); });  // times out
  order.push(2);
}

beforeAll(asyncFunc);

beforeEach(() => {
  order.push(3);
});

it("should run in order", () => {
  expect(order).toEqual([1, 2, 3]);  // FAIL: [1, 3] and Timeout error
});

这篇关于在调用beforeEach()之前,异步beforeAll()不会完成的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆