Home

Awesome

spawn-with-mocks

Mock shell commands with JavaScript

Intended for testing shell scripts while mocking specific commands. Make assertions about the input for each command, and/or mock their stdout, stderr, and exit codes.

Build Status codecov

Example

In this script, we use curl to make a network request, then grep to filter by the letter F:

# example.sh

curl "<example-url>" | grep F

When testing the script, we decide to mock curl, but not grep:

const spawn = require('spawn-with-mocks').spawnPromise
const assert = require('assert')

const curl = (input) => {
  // The mock will receive the input
  // that was passed to the shell command
  assert.strictEqual(input, '<example-url>')
  // Defining the mock output:
  return {
    code: 0,
    stdout: ['Frog', 'Shrimp', 'Crab'].join('\n'),
    stderr: ''
  }
}

const options = {
  mocks: {
    curl
  }
}

spawn('sh', ['./example.sh'], options).then(data => {
  assert.deepStrictEqual(data, {
    code: 0,
    signal: '',
    // grep is not being mocked, so the
    // actual grep command will be used
    stdout: 'Frog\n',
    stderr: ''
  })
})

API

spawn (command[, args][, options])

Wrapper for child_process.spawn, with a new option called mocks. It returns a new ChildProcess.

options.mocks

Each key is a shell command, and the values are functions that should return an Object, Number, or String.

Object

When returning objects, they can have the following properties:

{
  // exit the command with this status code (default: 0)
  code: Number,
  // pipe this to stdout (default: '')
  stdout: String,
  // pipe this to stderr (default: '')
  stderr: String
}

Number

If a mock returns a number, it will be used as code

String

If a mock returns a string, it will be used as stdout

options.stdio

type: String|Array

The function also modifies the native stdio option. The last element of stdio will always be 'ipc', because the library uses that to message the spawned process. A ChildProcess can only have one IPC channel, so 'ipc' should not be set by the input options.

spawnPromise (command[, args][, options])

Like spawn, but it returns a Promise that resolves when the ChildProcess fires the close event. The resolved value is an object with these properties:

{
  // The process exit code
  code: Number,
  // The signal that terminated the process
  signal: String,
  // The stdout from the process
  stdout: String,
  // The stderr from the process
  stderr: String
}

How it Works

Each mock is an executable that's stored in a temporary PATH directory. Currently, the mocks do not work for all commands (such as builtins). This could be changed in a future version by using shell functions to create the mocks.

See Also

jest-shell-matchers - make assertions about the output from spawn-with-mocks

LICENSE

MIT