Let’s go through the process of setting up JEST with our React application, writing our first test and mocking an api call.
Setup
First we’ll need to install dependencies via yarn
yarn add enzyme yarn add enzyme-adapter-react-16 yarn add jest yarn add jest-enzyme yarn add nock
And add jest to our package.json to fire up JEST
"scripts": { "start": "webpack-dev-server --mode development --open --hot --progress", "build": "webpack --mode production", "test": "jest" },
We’ll also need a JEST setup file to load the enzyme adapter for React
import { configure } from 'enzyme'; import Adapter from 'enzyme-adapter-react-16'; configure({ adapter: new Adapter() });
File Layout
__mockData__/[mock json files] __mocks__/[test files] jest.setup.js package.json
Mock Data
Rather than interact with live data we need to mock any data we give our tests so we have a staple ground with which to interact with our application.
We’ll do this quite simply by storing our mock data in JSON files and pulling it in much like how our api would send it.
// __mockData__/videos.json [ { "id": "01" "title": "Avengers Infinity War" }, { "id": "02" "title": "Avengers Endgame" } ]
#
Now lets move to writing our first test. For this example we’re going to use a simple Async request and then use Nock to intercept the GET request and give it the data from our videos.json file.
First our sample API call
//../src/videoRequest.js import request from 'superagent'; async function listVideos(category) { return await request .get(`/v1/videos/category/${category}`) .set('accept', 'json') .then(function(response) { return response.body }); } export { listVideos }
And now our Test
// __tests__/testAPI.js import React, { component } from 'react'; import { mount, shallow } from 'enzyme'; import toJSON from 'enzyme-to-json'; import nock from 'nock'; // load helper get method for video categories import listVideos from './../src/videoRequest'; // load mock data let mockVideos = require('./../__mockData__/videos.json'); // setup get intercepts, // specifying the API path and data to return. nock('http://localhost') .get('/v1/videos/') .reply(200, { mockVideos }); nock('http://localhost') .get('/v1/videos/category/all') .reply(200, { mockVideos }); // describe tests describe('videoRequest Component', () => { describe('when helpers fired', () => { // define test, applying async similar to the live version it('return videos in category all', async () => { // fire get request const results = await listVideos('all') // define expected returned data expect(results.mockVideos[0].title).toEqual("Avengers Infinity War") }) }) });
Notice at the start we load the mock data into memory.
let mockVideos = require('./../__mockData__/videos.json');
Then knoking the API route the request will use we tell nock to intercept that very path and method returning it that very same data.
nock('http://localhost') .get('/v1/videos/category/all') .reply(200, { mockVideos });
That way when we test the data give we can have predictable results.
expect(results.mockVideos[0].title).toEqual("Avengers Infinity War")
We can use this same method to mock other GET requests, POST requests, error handling for front-end so we’re able to test out our components without them touching live data.