我正在嘗試使用 Jest 在 nodeJS 中撰寫一個測驗,該測驗一個接一個地呼叫兩個異步函式。我想延遲 funcA,期望 funcB 不被呼叫,然后運行計時器并期望 funcB 被呼叫。
代碼看起來像這樣
//module1.js
async function mainFunc() {
await module2.funcA()
await module2.funcB()
}
//module2.js
async function funcA(){
// making some async operation
}
async function funcB(){
// making some async operation
}
我試過像這樣模擬 funcA 的實作:
const spyOnFuncA = jest.spyOn(module2, 'funcA').mockImplementation(async () => new Promise((r) => setTimeout(r, 1000)))
然后在測驗中做這樣的事情:
test('Should not call second function until first function resolved', async () => {
jest.useFakeTimers()
const spyOnFuncA = jest.spyOn(module2, 'funcA').mockImplementation(async () => new Promise((r) => setTimeout(r, 1000)))
const spyOnFuncB = jest.spyOn(module2, 'funcB').mockImplementation()
mainFunc()
expect(spyOnFuncA).toBeCalled()
expect(spyOnFuncB).not.toBeCalled()
jest.runAllTimers()
expect(spyOnFuncB).toBeCalled()
})
我認為這里的問題是jest.useFakeTimers
與 mockImplementation 中的 setTimeout 相矛盾
任何想法我應該如何測驗這個?
將不勝感激任何想法
干杯!
uj5u.com熱心網友回復:
模擬funcA
回傳延遲的承諾,稍后解決。我知道 sinon 提供了一個promise helper來覆寫 deferred 所以 jest 可能包含一個類似的結構。否則,這是該答案的簡單實作之一:
class Deferred {
constructor() {
this.promise = new Promise((resolve, reject) => {
this.reject = reject
this.resolve = resolve
})
}
}
然后模擬是這樣的:
const deferred = new Deferred()
const spyOnFuncA = jest.spyOn(module2, 'funcA').mockImplementation(() => deferred.promise)
mainFunc() // avoid uncaught exceptions with `.catch`
.catch(err => expect(err).toBe(null))
expect(spyOnFuncA).toBeCalled()
expect(spyOnFuncB).not.toBeCalled()
await deferred.resolve('whatever')
expect(spyOnFuncB).toBeCalled()
uj5u.com熱心網友回復:
假計時器方法是正確的,但您需要等待從mainFunc
完成回傳的承諾。
module1.js
:
import * as module2 from './module2';
export async function mainFunc() {
await module2.funcA();
await module2.funcB();
}
module2.js
:
export async function funcA() {
// making some async operation
}
export async function funcB() {
// making some async operation
}
module1.test.js
:
import { mainFunc } from './module1';
import * as module2 from './module2';
describe('73707110', () => {
test('Should not call second function until first function resolved', async () => {
jest.useFakeTimers();
const spyOnFuncA = jest.spyOn(module2, 'funcA').mockImplementation(() => new Promise((r) => setTimeout(r, 1000)));
const spyOnFuncB = jest.spyOn(module2, 'funcB').mockImplementation();
const promise = mainFunc();
expect(spyOnFuncA).toBeCalled();
expect(spyOnFuncB).not.toBeCalled();
jest.runAllTimers();
await promise;
expect(spyOnFuncB).toBeCalled();
});
});
測驗結果:
PASS stackoverflow/73707110/module1.test.ts (10.534 s)
73707110
? Should not call second function until first function resolved (4 ms)
------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
------------|---------|----------|---------|---------|-------------------
All files | 100 | 100 | 33.33 | 100 |
module1.ts | 100 | 100 | 100 | 100 |
module2.ts | 100 | 100 | 0 | 100 |
------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 11.156 s
"jest": "^26.6.3"
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/508476.html