7

I am using nock library to stub my http calls. Different test files require('nock') and do their stubbing. If each test is run separately, all is passing. But if all tests run together, later tests fail because instead of nock, actual request was made.

Consider below code snippet for example. It has two different describe blocks, each with multiple test cases. If I run this file node node_modules/mocha/bin/_mocha test.js then the first two tests will pass, but the third test (in different describe block) would fail because it would actually call the google URL.

/* eslint-env mocha */

let expect = require('chai').expect
let nock = require('nock')
let request = require('request')

let url = 'http://localhost:7295'

describe('Test A', function () {
  after(function () {
    nock.restore()
    nock.cleanAll()
  })

  it('test 1', function (done) {
    nock(url)
      .post('/path1')
      .reply(200, 'input_stream1')

    request.post(url + '/path1', function (error, response, body) {
      expect(body).to.equal('input_stream1')
      done()
    })
  })

  it('test 2', function (done) {
    nock(url)
      .post('/path2')
      .reply(200, 'input_stream2')

    request.post(url + '/path2', function (error, response, body) {
      expect(body).to.equal('input_stream2')
      done()
    })
  })
})

// TESTS IN THIS BLOCK WOULD FAIL!!!
describe('Test B', function () {
  after(function () {
    nock.restore()
    nock.cleanAll()
  })

  it('test 3', function (done) {
    nock('http://google.com')
      .post('/path3')
      .reply(200, 'input_stream3')

    request.post('http://google.com' + '/path3', function (error, response, body) {
      expect(body).to.equal('input_stream3')
      done()
    })
  })
})

Funny thing is, if I do console.log(nock.activeMocks()), then I can see that nock did register the URL to mock.

[ 'POST http://google.com:80/path3' ]
Rash
  • 6,184
  • 1
  • 42
  • 58

1 Answers1

4

As discussed in this Github Issue, nock.restore() removes the http interceptor itself. When you run nock.isActive() after calling nock.restore() it will return false. So you need to run nock.activate() before using it again.

Solution 1:

Remove nock.restore().

Solution 2:

Have this before() method in your test.

  before(function (done) {
    if (!nock.isActive()) nock.activate()
    done()
  })
Rash
  • 6,184
  • 1
  • 42
  • 58
  • 1
    thanks! you saved me a few minutes tracking that down in the docs! – subelsky Aug 09 '18 at 18:53
  • Can you explain what your problem was, and if there was any error message? – Rash Sep 04 '19 at 10:55
  • my `before` is async thats why i can not use done(). I put nock.cleanAll() inside `afterEach` – Omar Faruque Sohag Sep 04 '19 at 13:42
  • I am not sure what you mean by before is async...if possible why don't you post another question and send me the link...I will try to answer that. – Rash Sep 04 '19 at 17:26
  • i am using dotenv package in another file.I think dotenv is causing not to mock url using nock.If i remove dotenv then it works but if i keep dotenv it requests the original url from env. :( – Omar Faruque Sohag Sep 12 '19 at 03:00
  • I tried something similar, but can't seem to get the test to be passing. Could you please have a look? https://stackoverflow.com/questions/59202099/testing-the-same-url-with-nock-mocha-and-lolex – codehitman Dec 05 '19 at 19:34