Joyful unit testing with Jest

+

+

=

<3

}

About me

Andrei Cacio

I do JavaScript at

I also contribute to 

How does a unit testing stack look like?

enzyme.js

How can a unit testing stack look like?

Everything you need in one place

Test coverage

Snapshot testing

Assertions

easy CLI

ESNext support

Parallel tests

Dead simple API

async tests

baked in mocking

powerful and fast watch mode

meaningful error messages

babel friendly

JSDOM support

Straightforward setup

$ npm i jest -D
...
"scripts": {
    "test": "jest"
  },
...

package.json

A pretty nice watch mode

Right off the bat file matching

Recursively looks for:

  • .spec.js?x
  • .test.js?x
  • **/__tests__/**/*.jsx?x

Easy ESNext support

.babelrc

{
    "presets": ["es2015", "react"]
}
$ npm i babel \
        babel-preset-react \
        babel-preset-es2017 \
        babel-jest -D

The syntax you already know

describe('some test', () => {
   beforeEach(() => { });
   afterEach(() => { } );

   it('should do something', () => {
      expect(1).toBe(1);
   });
});

Unit tests run in parallel

"Jest parallelizes test runs across workers to maximize performance"

Spying, stubbing beautifully baked in

// Function spying
const spy = jest.fn();

expect(spy).toHaveBeenCalledTimes(0);
expect(spy).toHaveBeenCalledWith(arg1, arg2);

Spying, stubbing beautifully baked in

// Checking for specific params
const firstParam = spy.mock.calls[0][1];

expect(firstParam).toEqual('something');

Spying, stubbing beautifully baked in

// Function stubbing
jest
  .spyOn(object, 'someMethod')

// Stubbing with implementation 
jest
  .spyOn(object, 'someMethod')
  .mockImplementation(() => console.log('I am a mock'));

Async tests with assertions for promises

import someFn from '../someModule';

describe('some test', () => {
   it('should resolve properly', () => {
      return someFn().then(result => {
         expect(result).toBe(...);
      });
   });
});

The "promise way"

Async tests with assertions for promises

import someFn from '../someModule';

describe('some test', () => {
   it('should resolve properly', async () => {
      await expect(someFn()).resolves.toBe(...);
   });
});

async/await

Snapshot testing

import React from 'react';

export default ({ label }) => <button>{label}</button>;
import React from 'react';
import renderer from 'react-test-renderer';

import Button from '../Button';

describe('<Button />', () => {
  it('should render the given label', () => {
    const tree = renderer.create(<Button label='click me' />).toJSON();
    
    expect(tree).toMatchSnapshot();
  });
});

Snapshot testing

// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`<Button /> should render the given label 1`] = `
<button>
  click me
</button>
`;

Snapshot testing

Pros:

- great for testing arbitrary sets of data

- great for testing React Components

 

Cons:

- it can be sooooo painful

- developers tend to abuse it

Built in module mocking

jest.mock('/path/to/module', () => /* local implementation */);

or write once use everywhere

jest.mock('./utils.js');

Built in module mocking

jest.genMockFromModule(moduleName);

A good combo combined with

Built in test coverage

$ npm run coverage
...
"scripts": {
  "test": "jest",
  "coverage": "jest --coverage",
}
...
   

package.json

Migrating to Jest

$ npm i -g jest-codmods

Thank you!

/andrei-cacio/joyful-unit-testing-with-jest

Please leave me your feedback !!!

(be gentle, or not)

Made with Slides.com