-
-
Notifications
You must be signed in to change notification settings - Fork 269
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
A humble request for an 'uncaughtException' error interceptor #475
Comments
Partly addresses #475, albeit via a somewhat hacky workaround.
Partly addresses #475, albeit via a somewhat hacky workaround.
Ok, so, this is a bit janky, but as of 12.2, you can intercept I'm down for a |
Yes, this is weird, but no more weird as testing of asynchronous code in general (without promises). The tested error is being thrown from an asynchronous callback and it terminates its "thread". The obvious limitation is that we can't put more tests behind the thrown error in the asynchronous function. The successful error match in Probably more legitimate API solution would be if Anyway, thanks for the restoration of the ability to just monkeypatch |
Fix #475 This is much easier to accomplish now that tap is using async-hooks-domain instead of old-style domains for error tracking across async scopes. Multiple uncaught exceptions can be handled, but they must be thrown in the precise order expected. If a test ends (implicitly or otherwise) with expected uncaught exceptions not having been seen, then that is a failure.
Alright! This totally works with murmurhash-native in the latest v13 release. const t = require('tap')
const {murmurHash} = require('murmurhash-native')
t.test('should not abort', function(t) {
t.plan(3)
t.expectUncaughtException(new Error("foo"))
murmurHash('hash me!', function(err, done) {
t.error(err)
t.ok(done)
throw Error("foo")
})
}) You can also expect multiple uncaughtException events, but they must emit in the exact order expected. If any are remaining at the end of the test, then it fails the test (since this happens at test end, technically it fails the parent test, if it's not the root tap object.) To get it, run |
Works with node >= 9.
|
Hm, it looks like this is a failing in the ability of I thought it might be feasible to detect this and just assign it to the most recently created domain. Unfortunately, that won't work if you have multiple tests with async behaviors (for example, parallel tests, or just tests that do a bunch of async work before eventually throwing). There's probably a way to work around this in tap specifically, only for version 8, but I'm not sure. Without the async hook working, it's always going to be dicey to guess, since tests can be running in parallel to one another, and it'll end up being the same kind of brittle approach that you were already using. At the very least, yes, this is a valid bug (or at least a shortcoming of the design that ought to be documented if it's not going to be fixable). Thanks for following up, and sorry I don't have a better answer :) |
Thanks for looking into it. Looks like I'm stuck with a workaround for a while. At least until I don't need to support node < 9 anymore. |
Yeah, no way to make this work with node v8. Documented on de3882a as a caveat. Sorry for the inconvenience :\ |
I have an unusual test case:
Utill tap v9 I just monkey patched
t.threw
to intercept the error. But starting from v10 it's impossible due to handler being set early and directly and not by a proxy function(e) => this.threw(e)
.So my only way now is to remove 'uncaughtException' listeners and fight with domain's uncaughtExceptionHandler - very nasty stuff.
But maybe there is a better way or
tap
could provide a legal api to test such cases?From the API perspective I imagine something like:
and the test will succeed only when the first thrown uncaught exception is
Error("foo")
;The text was updated successfully, but these errors were encountered: