javascript - Aszinkron kód tesztelése Jest-ben: a done() nem hívódik meg a vártnak megfelelően
Itt egy Jest (v20.0.4) verzióban írt tesztcsomag található.
Az első 3 teszt várható viselkedés, a kérdésem a Teszt4-hez kapcsolódik.
test('Test1: the list should contain 7', () => {
const data = [1, 2, 7, 9];
expect(data).toContain(7);
});
// > Passes as expected
test('Test2: the list should contain 7', () => {
const data = [1, 2, 7, 9];
expect(data).toContain(8);
});
// > Fails as expected; Expected array: [1, 2, 7, 9] To contain value: 8
test('Test3: the list should contain 7', (done) => {
function callback(data) {
expect(data).toContain(7);
done();
}
setTimeout(() => {
callback([1, 2, 7, 9]);
}, 500);
});
// > Passes as expected
test('Test4: the list should contain 7', (done) => {
function callback(data) {
expect(data).toContain(8);
done();
}
setTimeout(() => {
callback([1, 2, 7, 9]);
}, 500);
});
// > Fails with Error "Timeout - Async callback was not invoked within timeout specified"
Itt van a kérdésem:
A Test4-ben a done() közvetlenül az expect utasítás után kerül meghívásra.
Tehát, még ha az expect utasítás nem is teljesül, azt gondoltam, hogy hibával kellene végződnie, hasonlóan a Test2-höz: (Várt tömb: [1, 2, 7, 9] hogy tartalmazza az értéket: 8)
Azonban időtúllépési hibával sikertelen, ahogyan fent látható, ami arra utal, hogy a done() soha nincs meghívva.
Miért? Nem értem!
Tudna valaki végigvezetni ezen a viselkedésen?
Átbogarásztam a dokumentumokat, de nem találtam semmit ezzel kapcsolatban.
Válasz #1
A kódodban a expect hívás hibát dob, és a done soha nem érhető el. Emiatt a Jest vár, amíg időtúllépés következik be, és kiadja a kellemetlen, zavaros hibát, amit észrevettél.
A megoldás az, hogy elkapjuk a dobást, és meghívjuk a done(error)-t, hogy jelezzük a Jest futtatónak, hogy a teszt megbukott.
test('Test4: the list should contain 7', done => {
function callback(data) {
try {
expect(data).toContain(8);
done();
}
catch (err) {
done(err);
}
}
setTimeout(() => {
callback([1, 2, 7, 9]);
}, 500);
});
Ennek a futtatása adja a kívánt eredményt:
Error: expect(received).toContain(expected) // indexOf
Expected value: 8
Received array: [1, 2, 7, 9]
A dokumentációból:
Ha a
expectállítás sikertelen, hibát dob, és adone()nem hívódik meg. Ha látni szeretnénk a teszt naplóban, hogy miért sikertelen, aexpect-et egytryblokkba kell csomagolnunk, és a hibát acatchblokkban át kell adni adone-nak. Ellenkező esetben egy átláthatatlan időtúllépés hibát kapunk, ami nem mutatja, hogy milyen értéket kapott aexpect(data).
Válasz #2
Rájöttem, hogy a setTimeout és a Jest nem úgy működik, ahogy az ember gondolná. De van egy jó módja annak, hogyan lehet vele megbirkózni:
A tesztje kezdete előtt megadhatja a Jestnek, hogy hamis időzítőket használjon:
jest.useFakeTimers();Amikor szükséged van arra, hogy a visszahívás végrehajtódjon, akkor a
jest.runAllTimers();segítségével indíthatod el.
https://jestjs.io/docs/en/timer-mocks.html
