-
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
expect.hasAssertions()
fails to mark the test as failed when using async function and callback
#4750
Comments
I'm not sure if I'm reading your repro correctly, but I suppose you're intentionally writing Attempting to make a simpler repro, using https://stackblitz.com/edit/vitest-dev-vitest-clv1dj?file=test%2Fexpect.hasAssertions-async.test.ts Show example codeimport { test, expect } from 'vitest';
test('simpler repro?', () => {
expect.hasAssertions();
// hasAssertions success + unhandled error
queueMicrotask(() => expect(0).toBe(1));
});
|
I think this is related to #3119 |
It seems that #3119 is about the event loop and not the micro-tasks queue. In our issue, if you make the callback async, there is no error because the callback is the first element in the virtual event loop of the Promise, which will be executed before the rest of the test function.
@hi-ogawa you are correct, I trimmed down a real case for the repro. |
The reason is the same though. |
Basically, if your test body cannot track its code execution, it is not the fault of the test runner. Just adding |
I'm not convinced that the test must fail. We could very well flush the queue and only then check the result of the assertions.
Yes, but it doesn't mean we can't help the user, alleviating some of the pain.
If you add One thing to keep in mind though is that very few developers know or understand the microtasks queue whereas most are familiar with async management. Meaning that it is less of a burden to tell them to manage their async calls than to tell them to manage their microtasks queue, which might very well be generated by a third-party library. |
This would mean that we basically change the developer's test function which I am totally against. The test function was provided to the test runner and we cannot temper with it in any way - if the developer didn't wait for a microtask queue to finish, it is intentional from the test runner's point of view.
Yes, by failing the test as described in #3119. |
Fair point. So what is left to do is to handle assertions properly when made in the microtask queue. I also noticed that flushing the microtask queue inside the test body doesn't fix the issue : // The test passes when it should fail
// hasAssertions success + unhandled error
test('flushing microtasks queue', async () => {
expect.hasAssertions();
queueMicrotask(() => {
expect(0).toBe(1);
});
await Promise.resolve();
}); |
It doesn't work because the default catch block cannot handle such cases. You can see it in the simple example (this is how it's processed internally): try {
queueMicrotask(() => {
throw new Error('error inside a microtask!')
});
await Promise.resolve();
} catch(err) {
// not called!
} |
Right. Is the solution to listen to That would require the error to carry the task id so it would only work for assertion errors, which is fair. |
We already do that, that's why you see the error in the first place and it's not lost. The problem is that it's not reliable to assign an error to a test when global |
That's a start !
EDIT : It just hit me. When the microtask function throws, we may be running a different test already |
No, it doesn't require anything. Only snapshots need that.
Yes, that's exactly my concern. |
While it's not optimal to reserve that feature to local Another option I see is to wait for the event loop & microtasks queue to be flushed before moving to the next test, so we can mark the latest test as failed (😉) if an error is thrown in the meantime, but that's incompatible with This inconsistency makes me lean towards the first, more simple option. |
Describe the bug
You are using
expect.hasAssertions()
and an async function that accepts a callback.In that callback you make some assertions. If one of those assertions fails, the test is marked as successful and an error is reported.
I see two possibilities :
expect.hasAssertions()
.Reproduction
https://stackblitz.com/edit/vitest-dev-vitest-a4gsaq?file=test%2Fexpect.hasAssertions-async.test.ts
System Info
Used Package Manager
npm
Validations
The text was updated successfully, but these errors were encountered: