delijati
delijati

Reputation: 431

Record all remote calls in a nodejs express app for testing

The goal is to have recored api tests. This test are kind of integration tests, they load the whole app with all its middlewares and intercepts the external http calls and records them.

In Python world exists "WebTest" and "VCRPY" for that.

The app:

'use strict';

const express = require('express');
const request = require('superagent');

var app = express();

app.get('/hammer/version', function(req, res) {
    request
        .get('http://httpbin.org/get')
        .end(function(err, response) {
            console.log(response.body);
            res.status(200).json({
                version: '0.1.0',
                url: response.body.url
            });
        });
});

module.exports = app;

The test:

/* global describe, it */
'use strict';

const request = require('supertest');
const app = require('./app.js');

var path = require('path');
var tape = require('tape');
var tapeNock = require('tape-nock');

// call tapeNock with tape and an options object
var test = tapeNock(tape, {
    fixtures: path.join(__dirname, 'fixtures')
});

describe('Version test', function() {
    this.timeout(0);

    it('test version', function(done) {
        test('record_version.json', function(t) {
            request(app)
                .get('/hammer/version')
                .expect(200, {
                    url: "http://httpbin.org/get",
                    version: '0.1.0'
                })
                .end(function(err, res) {
                    if (err) return done(err);
                    t.end();
                    done();
                });
        });
    });
});

The "package.json":

{
  "name": "remote_node_test",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "dependencies": {
    "express": "^4.14.0",
    "mocha": "^3.2.0",
    "nock": "^9.0.2",
    "superagent": "^3.3.1",
    "supertest": "^2.0.1",
    "tape": "^4.6.3",
    "tape-nock": "^1.4.0"
  },
  "devDependencies": {
    "mocha": "^3.2.0"
  },
  "scripts": {
    "test": "mocha"
  },
  "author": "",
  "license": "ISC"
}

The test are run with "mocha":

NOCK_BACK_MODE=record  node_modules/mocha/bin/mocha 

First run works, second run with "lockdown/record" does not work.

The error:

% NOCK_BACK_MODE=lockdown  node_modules/mocha/bin/mocha test.js                                                                                                                              :(


  Version test
TAP version 13
# details.json
    1) return current version


  0 passing (32ms)
  1 failing

  1) Version test return current version:
     TypeError: Cannot read property 'status' of undefined
      at Test._assertStatus (node_modules/supertest/lib/test.js:263:10)
      at Test._assertFunction (node_modules/supertest/lib/test.js:281:11)
      at Test.assert (node_modules/supertest/lib/test.js:171:18)
      at Server.assert (node_modules/supertest/lib/test.js:131:12)
      at emitCloseNT (net.js:1553:8)
      at _combinedTickCallback (internal/process/next_tick.js:71:11)
      at process._tickCallback (internal/process/next_tick.js:98:9)

Recorded are all requests, but i need only to record the "external" requests, and prevent "mocking/recording" my internal logic.

Upvotes: 4

Views: 1858

Answers (2)

delijati
delijati

Reputation: 431

One solution seems "replay" and configuring "passThrough" of requests to my local app.

/* global describe, it */
'use strict';

const request = require('supertest');
const app = require('./app.js');

var path = require('path');
const Replay = require('replay');

Replay.fixtures = __dirname + '/fixtures/replay';
Replay.passThrough('localhost', '127.0.0.1', '0.0.0.0');

describe('Version test', function() {
    this.timeout(0);

    it('test version', function(done) {
        request(app)
            .get('/hammer/version')
            .expect(200, {
                url: "http://httpbin.org/get",
                version: '0.1.0'
            })
            .end(function(err, res) {
                if (err) return done(err);
                done();
            });
    });
});

Upvotes: 1

Flet
Flet

Reputation: 479

If you're using mocha, you may want to look for a similar nock/nockBack helpers that are mocha-specific (https://www.npmjs.com/search?q=mocha+nock)

That being said, you may also run into problems where the HTTP call supertest makes to the app gets picked up by nockBack.

I made a little example that uses only tape to do what you're trying to accomplish: https://github.com/Flet/tape-nock-with-supertest-example

The afterRecord and before functions defined in setup-tape-nock.js are probably the secret sauce you would need even if using some other nockBack mocha helper.

Hope this helps!

Upvotes: 3

Related Questions