Avoid fixtures
that are defined outside of the test suite as a common fixture and used in multiple suites.
When debugging a Jest test, console.log
in the actual implementation, not in the test.
Testing specific assertion:
jest some_test.test.js -t "expression matcher for a test description"
toBe
vs toEqual
vs toStrictEqual
toBe
is a primitive comparison.
string
.toEqual
is a deep comparison.
array
and objects
.Two identical objects can have identical toEqual
but different toStrictEqual
or toBe
toStrictEqual
tests referencetoBe
tests Object.is()
toEqual
tests valuesRule: avoid
toBe
and prefertoStrictEqual
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
// 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); }) })
react-router
and Apollo
Uses jest.requireActual
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(), }));
mockResolvedValueOnce
.mockResolvedValueOnce(value);
Is a syntactic sugar for:
jest.fn().mockImplementationOnce(() => Promise.resolve("some value"));
With above, you have to mock the import first before calling the mockResolvedValueOnce
:
import someModule from 'someModule'; jest.mock('someModule', () => { someMethod: jest.fn() }); // assertion (someModule.someMethod as jest.Mock).mockResolvedValueOnce("some value");
When importing a default nested file, here is the syntax:
import someModule from 'someLibrary/someDomain'; jest.mock('someLibrary/someDomain', () => ({ default: jest.fn(), }));
mockResolvedValueOnce
would be used to guarantee the called expression returns the mock once:
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()
Tests whether a mock function successfully returned at least one time
test('fn returns', () => { const testFn = jest.fn(()=>true); testFn(); expect(testFn).toHaveReturned(); })
spyOn
You can spyOn
default exports using following syntax:
import * as someModuleDefaultExport from 'someModule'; someModuleDefualtExportSpy = jest.spyOn( someModuleDefaultExport, 'someModuleDefaultExport' )
.resolves
and .rejects
By using .resolves
matcher, Jest will wait for that Promise to resolve.
// 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); });