Ensure an Explicit Number of Expectations Within a Spec in Jasmine
QUnit and js-test-driver have ways of specifying how many assertions will be executed in a test case (expect and expectAsserts respectively) but Jasmine doesn’t. But it can still be done - here’s how.
Why would anyone want to count the number of expectations in a test
Normally Jasmine specs are pretty straightforward (assuming
systemUnderTest is defined somewhere else):
1 2 3 4
There are no branches, and you know Jasmine is going to run through all the expectations, one after the other. But it gets more complicated when loops, or async specs are involved. For example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
Here there is an array of arguments, each of which should cause the method
systemUnderTest.methodToTest to throw an exception. So we loop through the array of arguments, and run an expectation for each of them.
We have to wrap the call to
methodToTest in a function, because it’s going to throw an exception - the function
methodWrapper is a partial used by
.bind to generate such a function. So each iteration of the loop will have a new version of
arg already plugged in. Then
expect can run it, catch the exception, and pass the test.
This is still simple enough, there is only one loop with one statement in it. But you can see how this could easily get out of hand. What if the code was a little more complex, and for some reason the expectations in the loop are not executed? It will look like the test has passed, and you will never know the difference.
The js-test-driver page gives another example, using workers (adapted to Jasmine)
1 2 3 4 5 6 7 8 9 10
If the worker doesn’t call the callback function, then the expectation will not be run, and once again, it will look like the test has passed when it hasn’t.
Defining the number of expected assertions in Jasmine
Jasmine doesn’t have a simple way to tell how many assertions have run, but digging into the code I found where to get the information - in version 1.3 at least:
Therefore the examples above can be rewritten as
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
1 2 3 4 5 6 7 8 9 10 11
A note on compatibility
This will work, but only in version 1.3 - with the new 2.0 version
currentSpec remains private.
There was a plugin, jasmine-intercept, that used to take care of that, but apparently it has now been superseded by where.js. I haven’t had a chance to look into that yet, for now I’ll stick to my quick and dirty workaround.