React Testing

David Medina
3 min readAug 6, 2021

What is Jest?

Jest is a testing framework for JavaScript that includes both a test-runner and assertion functions in one package.

Installing Jest

Jest is included by default when initializing a React app using create-react-app. However, when manually installing Jest with npm, use the provided command to install it as a developer dependency.

npm install jest --save-dev

Configuring Jest

To configure Jest to run tests with the npm test command, the package.json file must have the "test" script defined.

  • The provided configuration will run the jest command on all files in the __test__/ directory with the extension .test.js or .spec.js.
  • The --coverage flag will produce a coverage report in the output and in the generated file coverage/index.html.
{   
"scripts": {
"test": "jest __tests__/ --coverage"
}
}

The test() function

Every Jest test begins with the test() function, which accepts two required arguments and one optional argument:

  • A string describing the functionality being tested
  • A callback function containing the testing logic to execute
  • An optional timeout value in milliseconds. The Jest test must wait for this timeout to complete before completing the test

Each test() function call will produce a separate line in the testing report. In order for a given test to pass, the test callback must run without throwing errors or failed expect() assertions.

The it() function is an alias for test().

test('test description', () => {
// testing logic and assertions go here...
}, timeout)

Detecting false positives

Jest will automatically pass a test that it perceives to have no expect() assertions or errors. As a result, false positives are likely to occur when naively testing code with asynchronous functionality.

To ensure that Jest waits for asynchronous assertions to be made before marking a test as complete, there are two asynchronous patterns that Jest supports, each with its own syntax for testing:

  1. Asynchronous callback execution can be tested with the done() parameter function.
  2. Promise values can be used in tests with the async/await keywords.

Testing async code: callbacks

When testing asynchronous code that uses a callback to deliver a response, the test() function argument should accept the done() callback function as a parameter. Jest will wait for done() to be called before marking a test as complete.

You should execute done() immediately after expect() assertions have been made within a try block and then again within a catch block to display any thrown error messages in the output log.

test('testing async code: callbacks`, (done)=>{
//act
asyncFunc(input, response => {
//assertions
try {
expect(response).toBeDefined();
done();
} catch (error) {
done(error);
}
});
}

Testing async code: Promises

When testing asynchronous code that returns a Promise, you must await the Promise and the callback passed to test() function must be marked as async.

test('testing promises', async () => {
//arrange
const expectedValue = 'data';
//act
const actualValue = await asyncFunc(input);
//assertions
expect(actualValue).toBe(expectedValue);
});

Mocking functions with jest.fn()

The Jest library provides the jest.fn() function for creating a “mock” function.

  • An optional implementation function may be passed to jest.fn() to define the mock function’s behavior and return value.
  • The mock function’s behavior may be further specified using various methods provided to the mock function such as .mockReturnValueOnce().
  • The mock function’s usage (how it was called, what it returned, etc…) may be validated using the expect() API.
const mockFunction = jest.fn(() => {
return 'hello';
});
expect(mockFunction()).toBe('hello');

mockFunction.mockReturnValueOnce('goodbye');

expect(mockFunction()).toBe('goodbye');
expect(mockFunction()).toBe('hello');
expect(mockFunction).toHaveBeenCalledTimes(3);

Mocking modules with jest.mock()

When mocking entire modules, mock implementations of the module should be created in a __mocks__/ folder adjacent to the file being mocked.

In the test files, the jest.mock() method may be used. It accepts a path to the file where the module to be mocked is defined and replaces the actual module with the version defined in the __mocks__/ folder.

The file to be mocked must be imported before it can be mocked with jest.mock().

// ../utils/utilities.js
export const someUtil = () => 'hello';

// ../utils/__mocks__/utilities.js
export const someUtil = jest.fn(() => 'goodbye');

// myTest.test.js
import { someUtil } from '../utils/utilities';
jest.mock('../utils/utilities');

test('using a mock function', () => {
expect(someUtil()).toBe('goodbye');
});

--

--