Mock your React components with Jest
First things first, let's install Jest :
npm install -g jest-cli
npm install react-tools --save-dev
You will then need to configure the tool to suit your setup, the easiest way to do that being to amend the
package.json
file directly :"jest": {
"rootDir": "relative/path/to",
"scriptPreprocessor": "<rootDir>/preprocessor.js",
"testDirectoryName": "tests",
"unmockedModulePathPatterns": ["<rootDir>/../../../../node_modules/react"]
},
Your test files will, according to this example, have to be located in a
relative/path/to/tests
folder. At the same level as this folder, you will have to set up a preprocessor.js
file such as the following :(function () {
'use strict';
var ReactTools = require('react-tools');
module.exports = {
process: function(src) {
return ReactTools.transform(src);
}
};
})();
As you can see, we make use of the
react-tools
package we installed beforehand, which is meant to compile your JSX files in a standalone way in order to feed them to Jest (and, underneath, Jasmine).The last line of the framework's configuration tells it not to mock React itself, as it automatically mocks pretty much everything and lets you decide what you want to preserve by using
jest.dontMock('something')
in your tests.As for it, my personal recommandation would be to turn automocking off in the first place, as it has brought me more trouble than benefits. You can do that by using
jest.autoMockOff()
, and use the reverse logic to mock just what you need with jest.mock('something')
. Actually, I have not been using that a lot, preferring to mock single methods here and there by replacing them with someModule.someMethod = jest.genMockFunction()
.Speaking of mocks, you should know there currently is an open issue about the fact you cannot spy on stubbed method calls when these calls are meant to happen in response to an user event, such as
onClick
and the likes.One great thing about tests is the way they make you think twice about your code. When using Jest, you will soon realize you want to avoid putting logic directly in methods such as
componentWillMount
, since they cannot be stubbed before the component's mounting into the DOM. Instead, put this logic in a separate function that will be called both by componentWillMount
and manually in your test, so you can stub things and toy around with your component's data before updating its rendering.If you need to mock a method that returns a promise and want to avoid using a dedicated library for that, here is a quick'n'dirty way to achieve just that :
jest.genMockFunction().mockReturnValue({
then: function(callback) {
callback(someArrayOrObjectOrWhateverThePromiseYields);
}
});
That will be all for now. Other small articles on the same topic may follow soon, stay tuned !
At the time of the writing of this article, I also had an issue where Jest would crash randomly, apparently because of some permission issue related to the
.haste_cache
folder. I tried running it with sudo
, which not only worked but was not necessary anymore after the single time I used it.