I thought this was difficiult to get working, but in retrospect, vitest was probably fine and I just missed a detail about how the code was structured.
After imported a few things from Vitest, exec is imported from the node:child_process module. Then, Vitest just mocks the entire parent module. The order actually doesn't matter since Vitest will hoist the mock call in a way that assures it works with the imported module.
Once that was working, my test didn't actually work -- it was spinning unitl it was cut off by Vitest's 5 second timeout. That was happening because the call-exec module wraps the exec
call in a Promise which resolves or rejects from the exec
callback, the wrapping promise could never be resolved by the mock, since the resolve
and reject
functions were inherited from the containing scope -- which the mocked function couldn't know about.
This was a simplified reduction of a quirk that I didn't see right away and ended up wasting too much time on. I refactored the testable parts out of the promise and moved on to other stuff.