Jest vs. Mocha: Why Jest Wins
Key Motivations for Jest
The "easier" part boiled down to three primary features:
- All dependencies are mocked by default
- Ease of setup and configuration
- Auto-magically finds and runs all your tests; no registration required
To Mock, or Not To Mock? Shouldn't be a Question
While explicit mocking seems fair, this may be attributed to everyone else also following this mentality. The vast majority of the time, you need to mock all dependencies except for the subject under test. Not mocking a particular dependency is typically an edge-case. If we usually mock everything but the SUT, why do frameworks have us do the exact opposite, not mock the SUT and explicitly define our mocks for everything else?
Here I agree with Jest's approach. Jest automatically mocks all dependencies unless otherwise specified. It allows us to set up our mocks for what is relevant to the test in question but still have all other dependencies be fakes. It also means that changing interactions with collaborators is quicker—no need for the unnecessary setup of a fake.
Configuration has Never Been Easier
If you use mocha/karma with CommonJS modules, you know those module paths can sometimes bite you, especially when configuring karma. I have come across various directory structures, and I have run into some path-related issue when configuring the client-side testing stack.
- Create your karma config file
- Include mocha, sinon, and chai karma frameworks, as well as the plugins for them (karma-mocha, karma-sinon, karma-chai, and karma-sinon-chai).
- Don't forget to include a karma plugin for your browser (IE, PhantomJS, Chrome, etc.)
- Include your source files and test files by registering them with karma
- Exclude your source files to prevent duplicate loads
- Include third-party dependencies to be used as CommonJS modules
- Using bower? Either explicitly add every bower package's main file to the config file or write custom code to pull them and translate them properly
- Using a CDN for some? Don't forget to include these explicitly
- Don't forget to exclude your node_modules folder from being processed as CommonJS modules
- Don't forget to include configuration for the plugins that enable you to use CommonJS with karma (karma-common-js).
- Create a test. Mock any require statements needed for the module and test.
- Create a
__tests__directory to contain your tests.
- Create a test. Tell Jest not to mock the SUT and setup any fakes required.
jestfrom the command line.
What about the third-party dependencies? What if my module or test needed jQuery from a bower_components directory? Or a CDN? How does it know where to find jQuery? The simple answer is it doesn't matter because it is a mocked dependency!
What about telling it where the test files are or where the source files are? Jest takes care of that by using the convention that all your tests are in the
What about the DOM manipulations? It utilizes
jsdom to allow the testing of DOM operations.
Overall, I am quite impressed with Jest. I am impressed enough to adopt it as my standard for client-side unit testing and recommend it to anyone else working with TDD for front-end development. However, there was one noticeable drawback: it is a little slow to run your tests. Compared to mocha/karma, it takes longer to run your tests. How much longer? Noticeable. Too long? Up for debate. Honestly, with all the benefits it brings to the table, I am ok sacrificing a little bit of test runner speed.