测试Promise链函数时未等待执行完成导致断言失败问题
Ah, I see the issue here—your Promise chain isn't actually waiting for those setTimeout calls to finish, and your test isn't waiting for the entire startGame flow to complete before checking the state. Let's break this down and fix it step by step.
First, the problem in your startGame function
Right now, when you do .then(setTimeout(this.dealToPlayer, 2000)), you're passing the return value of setTimeout (a numeric timer ID) to .then()—but .then() expects a function that returns a Promise (or a plain value). Since setTimeout doesn't return a Promise, the Promise chain moves on immediately, skipping the delay and not waiting for the dealToPlayer call to run. The same issue applies to the 4-second setTimeout for the dealer.
Fix 1: Wrap setTimeout in a Promise utility function
First, create a simple helper to convert setTimeout into a Promise that resolves after the specified delay:
const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms));
Fix 2: Update startGame to use this delay and return the Promise chain
Modify your startGame function to use the delay helper, so the Promise chain properly waits for each delay before executing the next step. Also, make sure to return the entire chain so tests can wait for it to complete:
startGame = () => { return this.buildDeck() .then(this.shuffleDeck) .then(this.dealToPlayer) // Wait 2 seconds, then deal a second card to the player .then(() => delay(2000)) .then(this.dealToPlayer) // Wait 4 seconds, then deal to the dealer .then(() => delay(4000)) .then(this.dealToDealer); };
Fix 3: Make your test asynchronous
Your test runs synchronously, so it checks playersHand immediately after calling startGame—way before any of the asynchronous deck building, shuffling, or dealing has finished. Update the test to wait for the startGame Promise to resolve:
Using async/await (the cleanest approach for modern testing frameworks like Jest or Vue Test Utils):
it('expects playersHand to have 2 cards once game started', async () => { await wrapper.instance().startGame(); expect(wrapper.state('playersHand').length).toEqual(2); });
If you prefer using the done callback style:
it('expects playersHand to have 2 cards once game started', (done) => { wrapper.instance().startGame() .then(() => { expect(wrapper.state('playersHand').length).toEqual(2); done(); }) .catch(error => done.fail(error)); // Catch errors to avoid test timeouts });
Why this works:
- The
delayfunction turns the callback-basedsetTimeoutinto a Promise, so the.then()chain pauses and waits for the delay to finish before executing the next step. - Returning the entire Promise chain from
startGamelets your testawaitor attach a.then()to it, ensuring you only check the state after all asynchronous operations instartGamehave completed.
内容的提问来源于stack exchange,提问作者The Walrus

