Migrating from Jasmine to Jest

Since the current application I help build runs about >1200 (and growing) Jasmine unit-tests, I figured migrating to Jest would be a pretty painless process. Snapshot testing was (and very much still is) a missing part of testing stack and was the catalyst for this migration. While creating simple snapshots was super easy and I’m excited to snapshot everything more, what I uncovered about our Jasmine setup was the more interesting issue.

Our 1200+ Jasmine tests were running in about ~1.5-2 seconds. I didn’t think much about that, but writing this now it’s an obvious red flag. Little did I know, but we were also skipping about 50-75 tests (~25 of which were failing) and Jasmine wasn’t picking up on this. I boiled the problem down to a memory leak we designed into some utilities within our system that Jasmine wasn’t able to handle, involving some of our ES6 features and some of our memoization. While not ideal, I knew there was a problem with our Jasmine setup, but not with Jest, so I left it at that and pursued the migration to Jest.

Switching the test command

The first step was adding an additional test commend. The existing test command was "test": "babel-node jasmine.config.js", so we could run our ES6 and babel plugins over our source files. Dropping in Jest was pretty seamless - "test": "jest".

Additional needs for global Setup

An unexpected find was that we needed additional global setup for Jest, but I narrowed this down to existing Jasmine tests, that required requiring additional globals, not being run properly. I’m not satisfied that we uncovered everything (or the perfect setup) for our missing globals, but what I had to add is below.

frontend/testUtils/helpers.js

require('babel-polyfill');constjquery=require('jquery');constjsdom=require('jsdom').jsdom;global.window=jsdom().parentWindow;// Make a global instance of jQuery available for testsglobal.$=jquery;+global.Cookies={+value_:'',++get(){+returnthis.value_;+},++set(value){+this.value_+=`${value};`;+},+};+window.location.assign=jest.fn();+window.history.pushState=jest.fn();+window.history.push=jest.fn();

Spying and mocking

You’ll notice the jest.fn(); additions in the above the snippet. Jest offers really powerful mocking that simplify setup and make clear any expectations about output. The mocking docs give a bunch of really great examples that helped me reach most of the implementations I have below

After

With the setup and mocking adjustments, the only roadblock was the before-mentioned missing/failing tests. These changes made me 100% more confident in our passing tests and convinced these changes were necessary.

Should you use Jest?

I’d encourage you to really dive into what your needs are and determine for yourself if Jest is the right tool. Finding missing/skipped tests was really scary, but a really great find. That made justifying time spent doing the migration very easy to discuss.