The classic jasmine async helper methodsSo let's look at an example. Suppose we want to test whether a focus event triggers the display of a tooltip. Since this behaviour happens asynchronously, you'd usually use jasmines runs() and waitsFor() functions to defer verifying your expectations until the code actually had a chance to run.
This has a couple of annoying limitations. First off, writing the test gets a bit more complicated and the test becomes harder to read. Next, if we’re only verifying such a simple behaviour (as a good unit test should) we end up duplicating the check in waitsFor() and in the actual expect() block. Admittedly, we could just leave out the last block, but that hurts the expressiveness of the test.
And then there’s the issue of time. Waiting for 200 ms doesn't seem that bad, but from my experience these things quickly add up. And what if we’re testing for something that’s happening with a larger delay? Making it even worse is the negative case. How long does it take until waitsFor() fails, if what we’re testing isn’t working (yet)? A timeout can be specified as another parameter to waitsFor but by default this is set at 5 seconds. And in the Unittestiverse, that is an eternity.
Using jasmine.ClockSo, here’s how we can test the same thing using jasmine.Clock:
This already reads a lot better in terms of describing the behaviour we’re interested in. It does completely hide the fact that the underlying code gets called asynchronously but I see that as a benefit in this case.
The other big benefit is that this test now runs in about 10 ms in my browser. No matter whether it fails or not.
I also like how this works internally. It's a simple idea, yet clever. And while clever things usually only end up causing trouble I don't mind taking that risk if it gives me such big benefits.
When you call Clock.tick(200) it executes the stored callbacks that were supposed to happen in that period, in the appropriate order. This happens synchronously from inside our test. So by the time we verify the expected behaviour, everything is hopefully in place.
After our test has run, jasmine restores the original functions and any other tests that might rely on the original behaviour should work fine.
I like it a lot and am wondering why I only stumbled upon it now. If I don't care about the aync-ness of some behaviour - which is the default case, as it is just an implementation detail of the language - I can create more expressive tests with less effort.
But tell me about your experience. Have you used this feature before? Did you run into problems? I have only just started writing the first tests in this way and maybe there are some caveats I should know?