-1

I'm using Jest, and need to setup a Web server for running tests and then tear it down afterwards.

How can I implement this?

ObiHill
  • 11,448
  • 20
  • 86
  • 135

1 Answers1

1

You can do this using beforeAll and afterAll Jest global methods.

  1. Create a module that defines your setup and teardown functions:
// server.js
import Fastify from 'fastify';

const fastify = Fastify({
    logger: false
});

const PORT = process.env.PORT || 8080;

function startServer()
{
    return new Promise(function (resolve) {
        fastify.get('/init', function(req, res){
            res.status(200).send('INIT');
        });

        fastify.listen(PORT, function(err, addr)
        {
            if(err)
            {
                console.log(err);
                process.exit(1);
            }

            resolve(addr);
        }); 
    });
}

function endServer()
{
    return new Promise(function (resolve) {
        fastify.close(resolve);
    });
}

export {startServer, endServer};
  1. Create a module to fetch data from running server:
// fetch.js

import fetch from 'node-fetch';

async function get(url_str, opts_obj)
{
    let res = await fetch(url_str);
    return (opts_obj && opts_obj.json) ? await res.json() : await res.text();    
}

export {get};
  1. Create a test file:
// main.test.js

import { startServer, endServer } from './server.js';
import { get } from './fetch.js';

beforeAll(function(){
    console.log('Jest - beforeAll()');
    return startServer().then(function(addr){
        console.log('Server started!');
        console.log(`Web server listening on ${addr}!`);
    });
});

test('Get data from server', async function(){
    let res = await get('http://localhost:8080/init');
    expect(res).toBe('INIT');
});

afterAll(function(){
    console.log('Jest - afterAll()');
    return endServer().then(function(){
        console.log('Server closed!');
    });
});
  1. Run test from command line:
npx jest main 

Note: Given than we are using ES modules we have to prefix our jest command:

NODE_OPTIONS=--experimental-vm-modules npx jest main

See ECMAScript Modules via Jest docs.

You can also use modern async/await syntax:

  1. Update server.js module:
// server.js

import Fastify from 'fastify';

const fastify = Fastify({
    logger: false
});

const PORT = process.env.PORT || 8080;

async function startServer()
{
    fastify.get('/init', function(req, res){
        res.status(200).send('INIT');
    });

    return await fastify.listen(PORT);
}

async function endServer()
{
    return await fastify.close();
}

export {startServer, endServer};

  1. Update main.test.js:
// main.test.js

import { startServer, endServer } from './server.js';
import { get } from './fetch.js';

beforeAll(async function(){
    console.log('Jest - beforeAll()');
    let addr = await startServer();
    console.log(`Server listening on ${addr}!`);
});

test('Get data from server', async function(){
    let res = await get('http://localhost:8080/init');
    expect(res).toBe('INIT');
});

afterAll(async function(){
    console.log('Jest - afterAll()');
    await endServer();
});

  1. Run jest command as in 4. above.

Note: type is module in package.json i.e. Node.js is interpreting .js files as ES modules. This is why we can use import syntax.

Note: The following dependencies were installed:

  • fastify
  • node-fetch

Note: Fastify is used as the Web server because it has a close method, which makes it seemingly trivial to close the server.

ObiHill
  • 11,448
  • 20
  • 86
  • 135