mock-request-queue

    1.1.0 • Public • Published

    mock-request-queue

    A super-simple mock for the request library. There's nothing fancy about this mock: no route, nor verb matching. It's just an ordered queue that is consumed as your code executes request. mock-request-queue doesn't break the Open/Closed Principle by overwriting / monkey patching anything. It's intended to be used with Dependency Injection (injecting an instance that meets the request interface into your modules).

    NOTE mock-request-queue doesn't implement the entire request interface, however common functions are supplied: request, request.get, request.post, request.put, request.patch, request.delete, request(...).pipe.

    Installation

    npm install --save-dev mock-request-queue

    Usage

    Given the following example module, which accepts an instance of request in it's constructor (e.g. constructor injection):

    // UserService.js
    module.exports = function UserService (request) {
      const getUser = (id) => {
        return new Promise((resolve, reject) => {
          request('https://github.com/losandes/supposed', (err, res, body) => {
            if (err) return reject(err)
            return resolve({ res, body })
          })
        })
      }
     
      return { getUser }
    }

    If we give the module an instance of MockRequest instead of the request library, we can remove network traffic, and live dependencies from our tests:

    const test = require('supposed')
    const { MockRequest } = require('mock-request-queue')
    const UserService = require('./UserService.js')
     
     
    test('when making a request with 2 args: (url, callback)', {
      given: () => {
        const request = new MockRequest()
        request.enqueue(null, { statusCode: 200 }, { id: 42, name: 'Zaphod' })
        return new UserService(request)
      },
      when: (userService) => userService.getUser(42),
      'it should resolve the enqueued request': (then) => (err, actual) => {
        then.ifError(err)
        then.strictEqual(actual.res.statusCode, 200)
        then.strictEqual(actual.res.statusMessage, 'OK')
        then.strictEqual(actual.res.request.href, 'https://github.com/losandes/supposed')
        then.strictEqual(actual.body.id, 42)
        then.strictEqual(actual.body.name, 'Zaphod')
      }
    })

    enqueue

    Use request.enqueue to add a mock response to an instance of MockRequest. The order in which you enqueue responses is the order that they will be executed when requests are made. request.enqueue accepts 3 arguments:

    • err {Error} - a mock request level error
    • response {Object} - the mock response
    • body {Object} - the mock body

    NOTE if you don't enqueue enough requests, additional requests will receive an error in their callback stating that a request wasn't enqueued.

    request

    An instance of MockRequest returns a function, which can be used without verbs:

    const { MockRequest } = require('mock-request-queue')
     
    request('https://github.com/losandes/supposed', (err, res, body) => { /*...*/ })
    request({
      method: 'GET',
      url: 'https://github.com/losandes/supposed'
    }, (err, res, body) => { /*...*/ })

    Verbs

    An instance of MockRequest returns a function that has get, post, put, patch, and delete verbs, which can be used instead of the main request function.

    const { MockRequest } = require('mock-request-queue')
     
    request.get('https://github.com/losandes/supposed', (err, res, body) => { /*...*/ })
    request.post({
      url: 'https://github.com/losandes/supposed'
    }, (err, res, body) => { /*...*/ })
    request.put({
      url: 'https://github.com/losandes/supposed'
    }, (err, res, body) => { /*...*/ })
    request.patch({
      url: 'https://github.com/losandes/supposed'
    }, (err, res, body) => { /*...*/ })
    request.delete('https://github.com/losandes/supposed', (err, res, body) => { /*...*/ })

    NOTE that enqueue does not perform route, nor verb matching.

    Streams

    To pipe a mock stream, skip passing the callback to request. First, let's look at an example writable stream / consumer:

    const { Writable } = require('stream')
     
    class TestWritable extends Writable {
      /**
       * Creates a Writable stream with support for running in a Promise
       * @param resolve {function} - the `resolve` function of a new Promise
       * @param reject {function} - the `reject` function of a new Promise
       */
      constructor (options) {
        super({ ...{ objectMode: true }, ...options })
     
        if (!options || !options.resolve || !options.reject) {
          throw new Error('Expected expectedBody, and resolve, and reject functions to be provided')
        }
     
        const { resolve, reject } = options
     
        this.buffers = []
        this.response = null
     
        this.on('response', (res) => { this.response = res })
        this.on('error', reject)
        this.on('end', () => resolve({
          res: this.getResponse(),
          body: this.getBody()
        }))
      }
     
      _write (chunk, encoding, next) {
        this.buffers.push(chunk)
        next()
      }
     
      getResponse () {
        return this.response
      }
     
      getBody () {
        return this.buffers.join('')
      }
    }

    Given a writable stream like this, we can:

    const fs = require('fs')
    const path = require('path')
    const test = require('supposed')
    const { MockRequest } = require('mock-request-queue')
     
    // <TestWritable> (from example above)
     
    test('when making a request with 2 args: (url, callback)', {
      given: () => {
        const request = new MockRequest()
        // you can enqueue, a string, an object, or a Readable stream
        request.enqueue(null, { statusCode: 200 }, '{ "message": "ok" }')
        request.enqueue(null, { statusCode: 200 }, { message: 'ok' })
        request.enqueue(
          null,
          { statusCode: 200 },
          fs.createReadStream(path.join(__dirname, 'README.md'))
        )
     
        return { request }
      },
      when: ({ request }) => {
        const results = [
          new Promise((resolve, reject) => {
            request('https://github.com/losandes/supposed')
              .pipe(new TestWritable({ resolve, reject }))
          }),
          new Promise((resolve, reject) => {
            request('https://github.com/losandes/supposed')
              .pipe(new TestWritable({ resolve, reject }))
          }),
          new Promise((resolve, reject) => {
            request('https://github.com/losandes/supposed')
              .pipe(new TestWritable({ resolve, reject }))
          })
        ]
     
        return Promise.all(results)
      },
      'it should pipe the request output to the given writable stream': (then) => (err, results) => {
        then.ifError(err)
     
        results.forEach((actual) => {
          then.strictEqual(actual.res.statusCode, 200)
          then.strictEqual(actual.res.statusMessage, 'OK')
          then.strictEqual(actual.res.request.href, 'https://github.com/losandes/supposed')
        })
      }
    })

    Install

    npm i mock-request-queue

    DownloadsWeekly Downloads

    0

    Version

    1.1.0

    License

    MIT

    Unpacked Size

    34 kB

    Total Files

    13

    Last publish

    Collaborators

    • losandes