mock-spawn
An easy-to-use mock for child_process.spawn
.
Key ideas
- All mock processes wrap a user-supplied, asynchronous "runner function" that calls a callback to indicate that the process is "done running"
- You can plug in a "strategy function" that returns runner functions for handling specific spawn invocations.
- When no specific runner function is found, a default function is used. The baked-in default returns an exit code of 0 and returns immediately. The default function may be overridden for fancier behavior.
- All the information on how many times
spawn
was invoked and the details of every invocation are available as attributes on the mock for later assertions - Testing simple cases requires no setup whatsoever
- A simple "sequence" strategy for being able to say: do this on the first invocation, do the other thing on the second invocation and so on is available for use
Usage
Common cases
var mockSpawn = ; // override child_process.spawn// this is a simplistic example; you can use a library like `mockery` to// set a new instance for every test. See examples/complete/test.jsvar mySpawn = ;spawn = mySpawn; // at this point you have mocked child_process.spawn to always exit 0// and write nothing to stdout or stderr // let's change the default processing to exit 1 always and write something// to stdoutmySpawn; // let's tell the mock to do specific things on sequential calls// in this case we exit 0 on the first call, 1 on the second call and so onmySpawnsequence;mySpawnsequence;mySpawnsequence;mySpawnsequence
Getting fancy with custom strategies
var mockSpawn = ; // basic stuffvar mySpawn = ;spawn = mySpawn; // we are now testing if our library under test retries spawn commands on error// when executing the `foo` command var count = 0;mySpawn;
API
The runner function
The runner function accepts a single callback that needs to be called with an
exit code and optionally a signal name. If you define a throws
property on
the runner object, it will throw that error synchronously to mimic the
behavior of child_process.spawn
. It will ignore everything else in this case,
and it will not "run" at all.
CAVEAT: The throws
value must be an instanceof Error
.
The runner function has access to the following attributes via this
this.stdout
- the standard output of the process to which it can writethis.stderr
- the standard error of the process to which it can writethis.command
- the command for thespawn
callthis.args
- the args for thespawn
callthis.opts
- the options object passed to thespawn
callthis.emit
- the emit method of the underlyingEventEmitter
The process "runs" until the runner calls the callback.
The strategy function
The strategy function accepts 3 arguments: the command, args and options passed
to the spawn
invocation. It can inspect these to return a customized runner
for just that invocation.
It can also return a falsy value to indicate that the default function should be used.
var mySpawn = require('mock-spawn')([verbose])
returns a function that can be plugged into child_process
as a replacement
for spawn
- verbose - true to see additional debug messages from this library
var fn = mySpawn.simple(exit-code, [output-data], [error-data])
returns a runner function that exits with the specified code and writes specific data to the output and error streams
Arguments are:
- exit-code: exit code for the process
- output-data: the data to be written to standard output
- error-data: the data to be written to standard error
mySpawn.setDefault(fn)
sets the default processing of all spawn invocations to use the runner function specified
- fn - a runner function to handler default processing
mySpawn.sequence.add(fn)
enables the sequence
strategy and calls the runner function supplied at the
specific point in the sequence.
- fn - the runner function to use. The nth call to
add
plugs a runner function for the nth invocation tospawn
Do not mix sequence.add
and setStrategy
calls for a specific run.
mySpawn.setStrategy(fn)
sets fn
as the strategy that will return runner functions on demand.
- fn - the function to be used as the strategy function.
Do not mix sequence.add
and setStrategy
calls for a specific run.
mySpawn.setSignals(obj)
sets obj
as a lookup table for whether to exit. If the value is true
,
then the runner will emit exit
with code null
and signal <signal>
.
- obj - the object with signal names and whether to exit.
mySpawn.calls
array of mock process objects that you can use to inspect how your library
under test invoked spawn
. Every object has the following properties available
command
- the commandargs
- the command argumentsopts
- the options passed to the spawn invocationexitCode
- the exit code of the processsignal
- the signal delivered to the process (simulated via the runner)
License
BSD. See accompanying LICENSE file.
Third-party libraries
The following third-party libraries are used by this module:
TODO
Pull requests welcome!
child_process.fork
andchild_process.exec
processing- strategy functions on
process.kill