I recommend Mrm and jest-codemods for single-command Jest installation and easy migration from other frameworks.
describe('makePoniesPink', () => { beforeAll(() => { /* Runs before all tests */ }) afterAll(() => { /* Runs after all tests */ }) beforeEach(() => { /* Runs before each test */ }) afterEach(() => { /* Runs after each test */ }) test('make each pony pink', () => { const actual = fn(['Alice', 'Bob', 'Eve']) expect(actual).toEqual(['Pink Alice', 'Pink Bob', 'Pink Eve']) }) })test('should be anything', () => { expect('foo').toBeCalledWith(expect.anything()); // true }); expect.anything() // matches anything except null or undefinedexpect.any(Number|String|Array|Function) // matches anything that was created with the given construct function randocall(fn) { return fn(Math.floor(Math.random() * 6 + 1)); } test('randocall calls its callback with a number', () => { const mock = jest.fn(); randocall(mock); expect(mock).toBeCalledWith(expect.any(Number)); });expect.arrayContaining([]) const expected = ['Alice', 'Bob']; it('matches even if received contains additional elements', () => { expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(expected)); });expect.objectContaining(object) test('onPress gets called with the right thing', () => { const onPress = jest.fn(); simulatePresses(onPress); expect(onPress).toBeCalledWith( expect.objectContaining({ x: expect.any(Number), y: expect.any(Number), }), ); });expect.stringContaining(string) // Deep equalityexpect.stringMatching(string | regexp) // matches the received value if it is a string that matches the expected string or regular expression.expect(42).toBe(42) // Strict equality (===) expect(42).not.toBe(3) // Strict equality (!==) expect([1, 2]).toEqual([1, 2]) // Deep equality expect({ a: undefined, b: 2 }).toEqual({ b: 2 }) // Deep equality expect({ a: undefined, b: 2 }).not.toStrictEqual({ b: 2 }) // Strict equality (Jest 23+)// Matches anything that an if statement treats as true (not false, 0, '', null, undefined, NaN) expect('foo').toBeTruthy() // Matches anything that an if statement treats as false (false, 0, '', null, undefined, NaN) expect('').toBeFalsy() // Matches only null expect(null).toBeNull() // Matches only undefined expect(undefined).toBeUndefined() // The opposite of toBeUndefined expect(7).toBeDefined()expect(2).toBeGreaterThan(1) expect(1).toBeGreaterThanOrEqual(1) expect(1).toBeLessThan(2) expect(1).toBeLessThanOrEqual(1) expect(0.2 + 0.1).toBeCloseTo(0.3, 5)expect('long string').toMatch('str') expect('coffee').toMatch(/ff/) expect('pizza').not.toMatch('coffee') expect(['pizza', 'coffee']).toEqual([expect.stringContaining('zz'), expect.stringMatching(/ff/)])expect(['Alice', 'Bob', 'Eve']).toHaveLength(3) expect(['Alice', 'Bob', 'Eve']).toContain('Alice') expect([{ a: 1 }, { a: 2 }]).toContainEqual({ a: 1 }) expect(['Alice', 'Bob', 'Eve']).toEqual(expect.arrayContaining(['Alice', 'Bob']))expect({ a: 1 }).toHaveProperty('a') expect({ a: 1 }).toHaveProperty('a', 1) expect({ a: { b: 1 } }).toHaveProperty('a.b') expect({ a: 1, b: 2 }).toMatchObject({ a: 1 }) expect({ a: 1, b: 2 }).toMatchObject({ a: expect.any(Number), b: expect.any(Number) }) expect([{ a: 1 }, { b: 2 }]).toEqual([ expect.objectContaining({ a: expect.any(Number) }), expect.anything() ])// const fn = () => { throw new Error('Out of cheese!') } expect(fn).toThrow() expect(fn).toThrow('Out of cheese') expect(fn).toThrowErrorMatchingSnapshot()Aliases
toThrowError→toThrow
expect(node).toMatchSnapshot() // Jest 23+ expect(user).toMatchSnapshot({ date: expect.any(Date) }) expect(user).toMatchInlineSnapshot()// const fn = jest.fn() // const fn = jest.fn().mockName('Unicorn') -- named mock, Jest 22+ expect(fn).toBeCalled() // Function was called expect(fn).not.toBeCalled() // Function was *not* called expect(fn).toHaveBeenCalledTimes(1) // Function was called only once expect(fn).toBeCalledWith(arg1, arg2) // Any of calls was with these arguments expect(fn).toHaveBeenLastCalledWith(arg1, arg2) // Last call was with these arguments expect(fn).toHaveBeenNthCalledWith(args) // Nth call was with these arguments (Jest 23+) expect(fn).toHaveReturnedTimes(2) // Function was returned without throwing an error (Jest 23+) expect(fn).toHaveReturnedWith(value) // Function returned a value (Jest 23+) expect(fn).toHaveLastReturnedWith(value) // Last function call returned a value (Jest 23+) expect(fn).toHaveNthReturnedWith(value) // Nth function call returned a value (Jest 23+) expect(fn.mock.calls).toEqual([['first', 'call', 'args'], ['second', 'call', 'args']]) // Multiple calls expect(fn.mock.calls[0][0](1)).toBe(2) // fn.mock.calls[0][0] — the first argument of the first callAliases
toBeCalled→toHaveBeenCalledtoBeCalledWith→toHaveBeenCalledWithlastCalledWith→toHaveBeenLastCalledWithnthCalledWith→toHaveBeenNthCalledWithtoReturnTimes→toHaveReturnedTimestoReturnWith→toHaveReturnedWithlastReturnedWith→toHaveLastReturnedWithnthReturnedWith→toHaveNthReturnedWith
expect(new A()).toBeInstanceOf(A) expect(() => {}).toEqual(expect.any(Function)) expect('pizza').toEqual(expect.anything())test('resolve to lemon', () => { expect.assertions(1) // Make sure to add a return statement return expect(Promise.resolve('lemon')).resolves.toBe('lemon') // return expect(Promise.reject('octopus')).rejects.toBeDefined(); })Or with async/await:
test('resolve to lemon', async () => { expect.assertions(2) await expect(Promise.resolve('lemon')).resolves.toBe('lemon') await expect(Promise.resolve('lemon')).resolves.not.toBe('octopus') })See more examples in Jest docs.
It’s a good practice to specify a number of expected assertions in async tests, so the test will fail if your assertions weren’t called at all.
test('async test', () => { expect.assertions(3) // Exactly three assertions are called during a test // OR expect.hasAssertions() // At least one assertion is called during a test // Your async tests })test('async test', async () => { expect.assertions(1) const result = await runAsyncOperation() expect(result).toBe(true) })Return a Promise from your test:
test('async test', () => { expect.assertions(1) return runAsyncOperation().then(result => { expect(result).toBe(true) }) })Wrap your assertions in try/catch block, otherwise Jest will ignore failures:
test('async test', done => { expect.assertions(1) runAsyncOperation() setTimeout(() => { try { const result = getAsyncOperationResult() expect(result).toBe(true) done() } catch (err) { done.fail(err) } }) })test('call the callback', () => { const callback = jest.fn() fn(callback) expect(callback).toBeCalled() expect(callback.mock.calls[0][1].baz).toBe('pizza') // Second argument of the first call })You can also use snapshots:
test('call the callback', () => { const callback = jest.fn().mockName('Unicorn') // mockName is available in Jest 22+ fn(callback) expect(callback).toMatchSnapshot() // -> // [MockFunction Unicorn] { // "calls": Array [ // ... })And pass an implementation to jest.fn function:
const callback = jest.fn(() => true)jest.mock('lodash/memoize', () => a => a) // The original lodash/memoize should exist jest.mock('lodash/memoize', () => a => a, { virtual: true }) // The original lodash/memoize isn’t requiredNote: When using
babel-jest, calls tojest.mockwill automatically be hoisted to the top of the code block. Usejest.doMockif you want to explicitly avoid this behavior.
-
Create a file like
__mocks__/lodash/memoize.js:module.exports = a => a
-
Add to your test:
jest.mock('lodash/memoize')
Note: When using
babel-jest, calls tojest.mockwill automatically be hoisted to the top of the code block. Usejest.doMockif you want to explicitly avoid this behavior.
const spy = jest.spyOn(ajax, 'request').mockImplementation(() => Promise.resolve({ success: true })) expect(spy).toHaveBeenCalled() spy.mockRestore()const location = {} const getTitle = jest.spyOn(location, 'title', 'get').mockImplementation(() => 'pizza') const setTitle = jest.spyOn(location, 'title', 'set').mockImplementation(() => {})const getTitle = jest.fn(() => 'pizza') const setTitle = jest.fn() const location = {} Object.defineProperty(location, 'title', { get: getTitle, set: setTitle })For one mock:
fn.mockClear() // Clears mock usage date (fn.mock.calls, fn.mock.instances) fn.mockReset() // Clears and removes any mocked return values or implementations fn.mockRestore() // Resets and restores the initial implementationNote:
mockRestoreworks only with mocks created byjest.spyOn.
For all mocks:
jest.clearAllMocks() // Clears the mock.calls and mock.instances properties of all mocks. Equivalent to calling .mockClear() on every mocked function. jest.resetAllMocks() // Resets the state of all mocks. Equivalent to calling .mockReset() on every mocked function. jest.restoreAllMocks() // Restores all mocks back to their original value, only mocks jest.spyOnjest.mock('fs') const fs = require('fs') // Mocked module const fs = require.requireActual('fs') // Original moduleWrite synchronous test for code that uses native timer functions (setTimeout, setInterval, clearTimeout, clearInterval).
// Enable fake timers jest.useFakeTimers() test('kill the time', () => { const callback = jest.fn() // Run some code that uses setTimeout or setInterval const actual = someFunctionThatUseTimers(callback) // Fast-forward until all timers have been executed jest.runAllTimers() // Check the results synchronously expect(callback).toHaveBeenCalledTimes(1) })Use jest.runOnlyPendingTimers() for special cases.
Or adjust timers by time with advanceTimersByTime().
Run the same test with different data:
test.each([[1, 1, 2], [1, 2, 3], [2, 1, 3]])('.add(%s, %s)', (a, b, expected) => { expect(a + b).toBe(expected) })Or the same using template literals:
test.each` a | b | expected ${1} | ${1} | ${2} ${1} | ${2} | ${3} ${2} | ${1} | ${3} `('returns $expected when $a is added $b', ({ a, b, expected }) => { expect(a + b).toBe(expected) })Don’t run these tests:
describe.skip('makePoniesPink'... tests.skip('make each pony pink'...Run only these tests:
describe.only('makePoniesPink'... tests.only('make each pony pink'...Node.js and Jest will cache modules you require. To test modules with side effects you’ll need to reset the module registry between tests:
const modulePath = '../module-to-test' afterEach(() => { jest.resetModules() }) test('first test', () => { // Prepare conditions for the first test const result = require(modulePath) expect(result).toMatchSnapshot() }) test('second text', () => { // Prepare conditions for the second test const fn = () => require(modulePath) expect(fn).toThrow() })Add babel-jest or ts-jest. Check their docs for installation instructions.
- Jest site
- Testing React components with Jest and Enzyme by Artem Sapegin
- React Testing Examples
- Testing React Applications by Max Stoiber
- Effective Snapshot Testing by Kent C. Dodds
- Migrating to Jest by Kent C. Dodds
- Migrating AVA to Jest by Jason Brown
- How to Test React and MobX with Jest by Will Stern
- Testing React Intl components with Jest and Enzyme by Artem Sapegin
- Testing with Jest: 15 Awesome Tips and Tricks by Stian Didriksen
- Taking Advantage of Jest Matchers by Ben McCormick: Part 1, Part 2
Improvements are welcome! Open an issue or send a pull request.
Artem Sapegin, a frontend developer at Wayfair and the creator of React Styleguidist. I also write about frontend at my blog.
CC0 1.0 Universal license, see the included License.md file.