gpt4 book ai didi

javascript - jest 带着 Promise 跳出函数

转载 作者:行者123 更新时间:2023-11-28 10:43:56 26 4
gpt4 key购买 nike

我正在尝试测试一个函数,该函数调用另一个模块的函数并返回一个 promise ,问题是 jest 不会等待 myFunction 完成,而是跳出它并将其视为 promise ,因为结果部分显示“done”消息在“resolve”消息之前打印。我可以使用 setImmediate 解决问题但我宁愿不使用它并想了解原因。

简化版本的代码如下:

被模拟的模块

// repo.js
const getItems = () => {
console.log('real');
return new Promise((resolve, reject) => {
setTimeout(
() => resolve('result'), 1000);
}
);
}
module.exports = {
getItems
};

被测单元:

 // sample.js
const repo = require('./repo');

const myFunction = (req, res) => {
console.log('myFunction');

repo.getItems()
.then(goals => {
console.log('resolve');
res.val = 'OK';
}).catch(err => {
console.log('reject');
res.val = 'Failed';
});

return;
};

module.exports = {myFunction};

测试文件:

// sample.test.js
const repo = require('./repo');
const sample = require('./sample');

const result = {
'message': 'done'
};
describe('Tests for receiving items', () => {
it('should call and be successful. ', () => {
repo.getItems = jest.fn(() => {
console.log('mocking');
return new Promise((resolve) => ( resolve(result) ));
});
const response = {val: 'test'};
const request = {};
sample.myFunction(request, response);
console.log('done');
expect(response.val).toBe('OK');
})
}
);

结果是:

  console.log MySample\sample.js:5
myFunction

console.log MySample\sampel.test.js:11
mocking

console.log MySample\sampel.test.js:17
done

console.log MySample\sample.js:9
resolve


Error: expect(received).toBe(expected)

Expected value to be (using ===):
"OK"
Received:
"test"
Expected :OK
Actual :test

最佳答案

您编写的测试反射(reflect)了正确的用法,您可能会说它达到了目的,因为它发现了实现中的错误。

为了展示到底出了什么问题,我将删除所有不需要的内容,这将导致一个更简单的示例。以下测试文件可以由 Jest 运行并重现您的问题。

const myFunction = (res) => {
Promise.resolve()
.then(goals => {
res.val = 'OK';
}).catch(err => {
res.val = 'Failed';
});

return;
};

it('should call and be successful. ', () => {
const response = {val: 'test'};
myFunction(response);
expect(response.val).toBe('OK');
})

myFunction 启动一个 Promise(在此处立即解析,没有任何值)并且不返回任何内容(undefined)。您还可以使用 Promise.reject 而不是 Promise.resolve 来测试错误部分。当您调用 myFunction(response) 时,下一行将在 myFunction 完成时执行。这不是 promise 实际完成的时间,而是函数本身的时间。该 promise 可能需要任何时间,并且您无法知道它何时真正完成。

为了能够知道 Promise 何时完成,您需要返回它,因此您可以在其上使用 .then() 来在 Promise 之后执行某些操作。已经解决了。 .then().catch() 都返回一个新的 Promise,该 Promise 会使用返回值进行解析,在本例中,返回值又是 undefined。这意味着您需要在 .then() 回调中进行断言。同样,Jest 认为测试在您退出函数时结束,即使它应该等待 Promise 得到解决。为了实现这一点,您可以从测试中返回 Promise,Jest 将等待其完成。

const myFunction = (res) => {
// Return the promise from the function, so whoever calls myFunction can
// wait for the promise to finish.
return Promise.resolve()
.then(goals => {
res.val = 'OK';
}).catch(err => {
res.val = 'Failed';
});
};

it('should call and be successful. ', () => {
const response = {val: 'test'};
// Return the promise, so Jest waits for its completion.
return myFunction(response).then(() => {
expect(response.val).toBe('OK');
});
})

您还可以使用async/await,但请记住,您仍然需要了解 Promise 的工作原理,因为它在底层使用了 Promise。 async 函数始终返回一个 Promise,因此 Jest 知道要等待其完成。

it('async/await version', async () => {
const response = {val: 'test'};
// Wait for the promise to finish
await myFunction(response);
expect(response.val).toBe('OK');
})

通常,您还会从 Promise 返回一个值(在 .then().catch() 中),而不是改变外部变量 (res )。因为如果您对多个 Promise 使用相同的 res,则会出现数据竞争,并且结果取决于哪个 Promise 首先完成,除非您按顺序运行它们。

关于javascript - jest 带着 Promise 跳出函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47037832/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com