Mock Express.js Client IP Address Using Jest
When working on an Express application that deals with the remote client IP address you might need to mock this IP address in your unit tests, this article shows how you can do this using Jest.
Example Express.js application
Create an example project:
$# Create a new directory and cd into it
$mkdir express-app
$cd express-app
$# Create a package.json file
$npm init -y
$# Install express
$npm i express
This is an example Express application that returns a JSON object containing the client’s IP address using req.ip
.
const express = require('express');
const app = express();
// Just return the client's IP address as JSON
app.get('/', (req, res) => res.json({ ip: req.ip }));
module.exports.app = app;
Note: By default, if the trust proxy
application variable is set to false
(default), then the IP is derived from req.connection.remoteAddress
otherwise it will be taken from the X-Forwarded-For
header depending on your configuration.
See: Express behind proxies for more details.
And this is the module that starts the application on port 3000
:
const { app } = require('./app');
const port = 3000;
app.listen(port, () => console.log(`Example app listening at http://localhost:${port}`));
Now you can start the application:
$node src/server.js
Example app listening at http://localhost:3000
And try it out:
$curl localhost:3000
{"ip":"::1"}
Mocking the req.ip
property
To test this application we’re going to use jest
and supertest
.
First install them as dev dependencies:
$npm i -D jest supertest
This is an example test file that shows how to mock req.ip
using jest.spyOn
:
const request = require('supertest');
const req = require('express/lib/request');
const { app } = require('../src/app');
const CLIENT_IP = '1.2.3.4';
beforeEach(() => {
// Mock the `ip` property on the `req` object
jest.spyOn(req, 'ip', 'get').mockReturnValue(CLIENT_IP);
});
afterEach(() => {
// Restore all the mocks back to their original value
// Only works when the mock was created with `jest.spyOn`
jest.restoreAllMocks();
});
test('Client IP', async () => {
const response = await request(app).get('/');
expect(response.statusCode).toBe(200);
expect(response.type).toBe('application/json');
expect(response.body.ip).toEqual(CLIENT_IP);
});
We are passing a third argument get
to jest.spyOn
because req.ip
is a getter function, check out the Jest documentation for more details.