Sinon: stubbing setImmediate by default leads to undesirable behavior

Created on 7 Jan 2016  ·  4Comments  ·  Source: sinonjs/sinon

I noticed this while trying to figure out why stubbing the system time caused csv writing to fail. It turns out that library had a setImmediate call that was blocking: https://github.com/C2FO/fast-csv/blob/master/lib/extended.js#L18

It seems like there are a bunch of libraries that rely on setImmediate for innocuous things, and that faking setImmediate leads to unexpected behavior in all of them:

Maybe it's unreasonable to expect that stubbing the system time does not cause csv writing to fail? In this case it's particularly difficult to track down, because in Javascript you can't just hit ctrl+c and get a stack trace showing you what went wrong. It took about 90 minutes just to identify what part of the code was freezing, and then to understand why sinon was responsible.

I'm not sure what the fix should be, but it seems to be affecting a lot of libraries, and at least one of them responded by creating its own version of setImmediate that can't be mangled with.

If the answer is I should be calling useFakeTimers(0, "Date"), maybe that should be the default? Maybe that fits better with my/people's expectations of how the world behaves?

Most helpful comment

For future reference, this form of the function now allows you to specify which functions are faked:

var clock = sinon.useFakeTimers([now, ]prop1, prop2, ...);

Sets the clock start timestamp and names functions to fake.

Possible functions are setTimeout, clearTimeout, setInterval, clearInterval, setImmediate, clearImmediate and Date. Can also be called without the timestamp.

So this solved the problem for me when working with express:

clock = sinon.useFakeTimers(1495020000, 'Date');

All 4 comments

I'm not sure what the fix should be, but it seems to be affecting a lot of libraries, and at least one of them responded by creating its own version of setImmediate that can't be mangled with.

That is the recommended solution for when you're using setTimeout, setImmediate for effect of getting a new call stack (and not for controlling time).

https://github.com/taylorhakes/promise-polyfill/pull/15

Yep, I just spent 90 minutes diagnosing and fixing this in a commercial codebase.

At the very least, the docs should mention that setImmediate will be faked.

For future reference, this form of the function now allows you to specify which functions are faked:

var clock = sinon.useFakeTimers([now, ]prop1, prop2, ...);

Sets the clock start timestamp and names functions to fake.

Possible functions are setTimeout, clearTimeout, setInterval, clearInterval, setImmediate, clearImmediate and Date. Can also be called without the timestamp.

So this solved the problem for me when working with express:

clock = sinon.useFakeTimers(1495020000, 'Date');

The documentation does explain this now: http://sinonjs.org/releases/v2.3.2/fake-timers/#var-clock--sinonusefaketimersnow-prop1-prop2-

Was this page helpful?
0 / 5 - 0 ratings