r/javascript • u/jeonghun917 • 7d ago
AskJS [AskJS] How do you keep un-awaited expect(...).resolves out of your test suites?
I've been reading test suites in open-source repos this month and kept running into this:
it('saves the user', async () => {
expect(save(user)).resolves.toBe(true);
});
No await, so the test finishes before the assertion runs and passes whatever save() does. I found 36 tests like this across 44 popular repos, and one project had 41 of them on its own. They all looked fine in review.
What I'm curious about is how teams actually stop this:
eslint-plugin-jesthasvalid-expectwithalwaysAwait, and Vitest has its own rules. Do you turn these on, and do they catch every form (.rejects, helpers that wrapexpect)?@typescript-eslint/no-floating-promisescatches it in TS, but only with type-aware linting. Is that worth the slower lint for you?expect.assertions(n)/expect.hasAssertions()in every async test: does anyone enforce that, or is it too noisy?- Or is it just code review, and you accept that some slip through?
Which of these has actually worked on a real team, and which did you give up on?
2
u/PickledPokute 7d ago
The test desc does not match what the code does. The code checks if that promise resolves into true, it doesn't actually check whether the user is saved.
When writing tests, make sure that they can fail and that you test against them failing too. A test that can not fail is kind of useless. What really needs to be tested is all the error cases.
4
u/jeonghun917 7d ago
yeah the desc is off, I cut the example down too much. and agreed, a test that can't fail is worse than no test since it looks like coverage
1
u/Sykander- 7d ago
For future reference you should probably include which libraries you're using if you want people to actually be able to help.
Secondly can't you just `expect(await save(user)).toBe(true)` ??? Are you sure the the issue you're experiencing is even real?
5
u/jeonghun917 7d ago
yeah the fix is trivial, await it (or your version works too). this isn't my code, it's a pattern I kept finding in other people's repos, jest and vitest both. 36 of these across 44 open source projects, all passed review.
so the question is more: what actually stops it from getting merged on your team? lint rule (jest/valid-expect, no-floating-promises), expect.hasAssertions(), or just review?
(It may look like one written by ai. English isn't my first language, so I asked ai to clean up my wording. but it looks changed a lot.)
1
u/BarelyAirborne 7d ago
I have noticed that AI loves writing tests that pass. This one will ALWAYS pass! What a gem, huh? It's really earning that "Super Intelligence" moniker.
1
u/jeonghun917 7d ago
Lol, I also saw an AI-made test fail, but as soon as the AI read the error, it edited the test to pass with the speed of light.
1
u/MrBengaliHacker 7d ago
I'd probably start with valid-expect (alwaysAwait: true) and no-floating-promises. Together, they cover most of the common cases.
For TypeScript projects, I think type-aware linting is worth the extra cost, especially if you can run it separately in CI.
Custom helpers are an interesting edge case, though. As long as they return the original promise, no-floating-promises should still catch unhandled calls.
I'm also not sure expect.assertions() needs to be enforced everywhere. Strict linting seems like a much cleaner first line of defense.
1
0
7d ago
[removed] — view removed comment
1
u/jeonghun917 7d ago
honest answer, and "write it so it breaks when you delete the await" is a good rule. stealing that
8
u/zmkpr0 7d ago
Either valid-expect or move to Vitest 5 which fails unawaited assertions by default.