Is there an option to set mocha to report test as failing in case no expect provided within it() function?
Idea is workflow to be like this:
- add one it() with desc and callback function
- the it() is reported as fail since no expectation is set in the callback
- expectation is added
- the it() is still reported as fail as expectation is not met since no implementation
- implementation is added
- the it() is reported as success
- refactor
So main intention is while doing canonical TDD style developing newly added test are reported as failed until expectation is set (or test set as pending without callback or skip()), which is again reported as fail and once implementation is done it is reported as success.
Value I see for it() succeeding without expectation is that once it is added it's failure now proves that it is actually working and proves it is failing. Was it intention or am I missing something?
Also, if anyone have idea how to set that up in karma.conf.js would be great.
Thanks
Mocha does not support what you want to do just by setting a flag. The closest thing is to use
it
without a callback:Mocha will treat this test as
pending
and report it as such. It is the same as usingit.skip(...)
. However, the test is not failed, and it does not catch stupid mistakes like having a loop that does not actually iterate:If it so happens that
a
is a 0-length array, then you'll not test anything, and the test will pass. In cases like this one I test that the array is not 0-length, but still...So there is no direct way to do it, and Mocha offers no API for assertion libraries to hook into to tell Mocha that they've actually been used in a test. You can build your own solution though. Here's a proof of concept:
In the code above, we replace
it
with our own, which does the check, and we replaceexpect
with our own to flag when it has been called.A note about asynchronous tests and shared state. Sometimes people think that Mocha will run multiple at the same time if they are marked as asynchronous. This is not normally the case. Mocha waits for one of two things before continuing after an asynchronous test: the test calls its
done
callback or it times out. You can have code from two tests running at the same time if the earlier test timed out and it so happens that the test that timed out was actually waiting for an asynchronous operation that completes after the time out. In such case, if there is any state that both tests depend on, the timeout can cause cascading test failures (or cascading test successes!). This is a general issue with Mocha. Once the timeout problem is fixed, then the cascading effect will disappear and subsequent tests will succeed or fail on their own merit, without being affected by earlier asynchronous tests that timed out. In the code above,expected_called
is a state that all tests depend on. So a timeout may cause cascading effects.To solve this problem, each test would have to have its own private instance of
expect
, which would only increment its own private counter. This could be done as follows:The disadvantage though is that you now have to access
expect
asthis.expect
, which means writing tests differently than you usually would. You may think that setting the globalexpect
before every test would eliminate the need to usethis
but this approach would be subject to exactly the same problem as I discussed above. (The global state shared by the tests would beexpect
itself instead ofexpect_called
.)