HomeToolsAbout a20k

Unit Test

Rules

Avoid fixtures that are defined outside of a test suite and used for multiple suites

  • Compromises the test isolation and makes it hard to change

Testing

Testing specific assertion

Test a select assertion

jest some_test.test.js -t "expression matcher for a test description"

Assertions

toBe vs toEqual vs toStrictEqual

Two identical objects can have identical toEqual but different toStrictEqual or toBe

  • toStrictEqual tests reference
  • toBe tests Object.is()
  • toEqual tests values

Rule: avoid toBe and prefer toStrictEqual

const a = { id: "1" }; expect(a).toEqual({ id: "1" }); // Pass expect(a).toStrictEqual({ id: "1" }); // Fail // `b` points to memory location of `a` const b = a; expect(a).toEqual(b); // Pass expect(a).toStrictEqual(b); // Pass

Special Assertions

// assertion to be implemented later it.todo() // run specified assertion exclusively describe.only() it.only() // positional injector parameter // %p is inserted to each assertion description describe.each([1, 2, 3])("each element %p exists", (el) => { test(`returns ${el}`, () => { expect(el).toBe(true); }) })

Mocking

Importing mocks of react-router and Apollo

jest.mock('react-router-dom', () => ({ ...(jest.requireActual('react-router-dom') as any), useParams: () => ({ id: 'abc-123' }), })); jest.mock('@apollo/client', () => ({ ...jest.requireActual('@apollo/client' as any, useQuery: jest.fn(), useMutation: jest.fn(), }));

Invocation Order

beforeAll(() => console.log('1')); afterAll(() => console.log('12')); beforeEach(() => console.log('2')); // 6 afterEach(() => console.log('4')); // 10 test('', () => console.log('3')); describe('Scoped / Nested block', () => { beforeAll(() => console.log('5')); afterAll(() => console.log('11')); beforeEach(() => console.log('7')); afterEach(() => console.log('9')); test('', () => console.log('8')); }); // 1 - beforeAll // 1 - beforeEach // 1 - test // 1 - afterEach // 2 - beforeAll // 1 - beforeEach // 2 - beforeEach // 2 - test // 2 - afterEach // 1 - afterEach // 2 - afterAll // 1 - afterAll

Methods

.mockResolvedValueOnce(value)

Syntactic sugar for:

jest.fn().mockImplementationOnce(() => Promise.resolve(value));
import {jest, test} from '@jest/globals'; test('async test', async () => { const asyncMock = jest .fn<() => Promise<string>>() .mockResolvedValue('default') .mockResolvedValueOnce('first call') .mockResolvedValueOnce('second call'); await asyncMock(); // 'first call' await asyncMock(); // 'second call' await asyncMock(); // 'default' await asyncMock(); // 'default' });

.toHaveReturned()

Purpose

Tests whether a mock function successfully returned at least one time

  • No param passed
test('fn returns', () => { const testFn = jest.fn(()=>true); testFn(); expect(testFn).toHaveReturned(); })

Async Jest

.resolves and .rejects

By using .resolves matcher, Jest will wait for that Promise to resolve.

  • If the Promise is rejected, it'll automatically fail.
// resolves test('testing Promise return expected resolved value', async () => { await expect( async () => await service.fetchData()).resolves.toBe('value'); }); // rejects test('testing Promise rejects to throw an expected error', async () => { await expect( async () => await service.fetchData()).rejects.toThrow(new NotFoundError().message); });
© VincentVanKoh