How to to run/close an http server as child process

不问归期 提交于 2019-12-11 17:13:38

问题


We have an application interacting with an (Node.js) HTTP server. To test the API calls, we have created a test HTTP server, which is working fine with the application. All the calls we make work as expected from the application.

Recently, we have been spending time trying to automate the testing of these API calls. One strategy we came up with was to:

  1. start the test HTTP server automatically;
  2. make calls to it;
  3. close the test HTTP server after the test.

Here is how our first test is written so far:

var serverHandler = require('../../server/serverHandler.js');

describe('Test the test server', function() {
  beforeEach(async () => {
    serverHandler.start(500, 'index.js'); // index.js: the HTTP test server.
                                          // 500: 500 ms of latency to mimic a slow response.

    result = await serverHandler.isRunning();
    expect(result).toEqual(true);
  });

  afterEach(async () => {
    serverHandler.kill();

    result = await serverHandler.isRunning();
    expect(result).toEqual(false);
  });

  test('Server is killed', async () => {
    // We could have more complex test logic here...
    serverHandler.kill();

    try {
      result = await serverHandler.isRunning();
      expect(result).toEqual(false);
    } catch (error) {
      expect(error).toEqual({
        error: 'server is running',
      });
    }
  });
});

Where the serverHandler is as follow:

const spawn = require('child_process').spawn;
const isReachable = require('is-reachable');

var child = null;

exports.start = (latency, path) => {
  child = spawn('node', [path, latency]);
};

exports.kill = () => {
  child.kill();
};

exports.isRunning = async () => {
  return await isReachable('http://localhost:8080');
};

As you can see, so far we are only trying to make steps 1 and 3 work, before adding anymore test logic. Sadly, it does not. When I run this test, I get the following output:

  ● Test the test server › Server is killed

    expect(received).toEqual(expected) // deep equality

    Expected: true
    Received: false

      14 | 
      15 |     result = await serverHandler.isRunning();
    > 16 |     expect(result).toEqual(true);
         |                    ^
      17 |   });
      18 | 
      19 |   afterEach(async () => {

      at toEqual (__tests__/integration/serverIntegrationExample.test.js:16:20)
      at tryCatch (node_modules/regenerator-runtime/runtime.js:45:40)
      at Generator.invoke [as _invoke] (node_modules/regenerator-runtime/runtime.js:271:22)
      at Generator.prototype.(anonymous function) [as next] (node_modules/regenerator-runtime/runtime.js:97:21)
      at tryCatch (node_modules/regenerator-runtime/runtime.js:45:40)
      at invoke (node_modules/regenerator-runtime/runtime.js:135:20)
      at node_modules/regenerator-runtime/runtime.js:145:13
      at tryCallOne (node_modules/promise/lib/core.js:37:12)
      at node_modules/promise/lib/core.js:123:15
      at flush (node_modules/asap/raw.js:50:29)

It looks like the server is never actually started. I know the test server is working well because all calls succeed in the application. I have found various sources speaking of similar problems, but most of them seem to be either dead ends, or make use of non-portable OS features, which is unacceptable for us (I am getting this output from Ubuntu).

What is(are) the problem(s) in this code and how can I achieve this? Also note, this is my first Node.js project, so any constructive advice on the code would be greatly appreciated.

EDIT

Here is the code for index.js:

const Express = require('express');
const multer = require('multer');
const bodyParser = require('body-parser');
const fs = require('fs');

const labelListMock = require('./mockData');

const uploadDirectory = './images';

const app = Express();
app.use(bodyParser.json());

const Storage = multer.diskStorage({
  destination(req, file, callback) {
    callback(null, uploadDirectory);
  },
  filename(req, file, callback) {
    callback(null, `${file.fieldname}_${Date.now()}_${file.originalname}`);
  },
});

const upload = multer({storage: Storage});

app.get('/', (req, res) => {
  res.status(200).send('You can post to /DispatchData.');
});


var latency = process.argv[2];

if (isNaN(latency)) {
  latency = 0;
}

app.use(function(req, res, next) {
  setTimeout(next, latency);
});


app.get('/RetrieveTypes', (req, res) => {
  res.status(200).json(labelListMock);
});

app.post(
  '/DispatchData',
  checkUploadPath,
  upload.single('photo'),
  (req, res, next) => {
    console.log('file', req.file);
    console.log('body', req.body);

    res.status(200).json({
      message: 'success!',
      fileName: req.file.originalname,
      category: 'buildAILabel',
    });
  },
);

module.exports = app.listen(8080, () => {
  console.log(
    'Mock server running on http://localhost:8080 (or http:://10.0.2.2:8080 if using an emulator.)',
  );
});


function checkUploadPath(req, res, next) {
  fs.exists(uploadDirectory, function(exists) {
    if (exists) {
      next();
    } else {
      fs.mkdir(uploadDirectory, function(err) {
        if (err) {
          console.log('Error in folder creation');
          next();
        }
        next();
      });
    }
  });
}

来源:https://stackoverflow.com/questions/58423661/how-to-to-run-close-an-http-server-as-child-process

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!