Mocking express-rate-limit for unit testing

This question is 4 months old and hasn't received a response so I'll do my best to explain it now that I've worked through and got it working.

So say you are using express-rate-limit like so:

middleware.js

const rateLimit = require('express-rate-limit')

const limiter = rateLimit({
  windowMs: 60 * 60 * 1000 * 24, // 24 hour window
  max: 5, // start blocking after 5 requests
  message:
    'Too many requests sent from this IP, please try again after an hour'
})

module.exports = {
   limiter
}

app.js

const middleware = require('./middleware')

router.post('/my-rate-limited-api', middleware.limiter, async (req, res) => {
  try {
    const info = await doSomething('my args', req.body)
    res.json(info)
  } catch (err) {
    res.status(err.status || 400).send(`error: ${err.message}`)
  }
})

To be able to test the things inside of this route, you'll need to stub limiter.

In your test file, make sure to include an IP in the req. And in your response, stub

req = {
      method: 'POST',
      ip: '12.12.123.123',
      url: '/my-rate-limited-api',
      body: [{ id: '123' }]
    }

and

res.headers = {}

and

res.setHeader = (x, y) => { res.headers[x] = y }

beforeEach(function () {
    const middleware = require('./middleware')
    this.sinon.stub(middleware, 'limiter').callsFake(function (req, res, next) {
      return next()
    })
    res = new Promise(function (resolve, reject) {
      doneResolve = this.resolve = resolve
      doneReject = this.reject = reject
    })
    res.headers = {}
    res.setHeader = (x, y) => { res.headers[x] = y }

    req = {
      method: 'POST',
      ip: '12.12.123.123',
      url: '/my-rate-limited-api',
      body: [{ id: '123' }]
    }

    next = this.sinon.spy(function createDeferredNext () {
      let resolve
      const promise = new Promise(function () {
        resolve = arguments[0]
      })
      const fn = (arg) => resolve(arg)
      fn.then = promise.then.bind(promise)
      return fn
    })
  })

From there, you'll be able to test your function however you like.


  it('can test without rate limits', function () {
    router(req, res, next)
    return res
      .then(ret => {
        expect(res.statusCode).to.eql(200)
      })
  })