elmer-fudd v1.3.1
elmer-fudd
A test runner for smallish node projects with an opinionated take on mocking and very few dependencies. It helps you hunt for Bugs... get it?
| Package | Why |
|---|---|
pirates | for patching require |
stack-trace | for identifying call sites |
Installation
$ npm install elmer-fuddMinimal Example Project
package.json
src/
multiply.js
scale.js
test/
multiply.test.js{
"elmer-fudd": {
"ext": "test.js",
"root": "test",
"alias": {
"@src": "src"
}
},
"scripts": {
"test": "elmer-fudd"
},
}const scale = require('./scale');
module.exports = (value) => value * scale;module.exports = 10;const { test, assert } = require('elmer-fudd');
test({
name: 'Multiply without mocking',
unit: '@src/multiply',
spec: (multiply) => {
assert.equal(multiply(5), 50);
}
});
test({
name: 'Multiply with mocked scale',
unit: '@src/multiply',
mock: [
['@src/scale', 2]
],
spec: (multiply) => {
assert.equal(multiply(5), 10);
}
});Testing Api
test
test takes a “test object” as an input, which allows you to specify a name, the unit you wish to test, any mocks you want to provide for dependencies, and a “spec” that runs assertions. Below are a few examples to get you started:
const { test, assert } = require('elmer-fudd');
test({
name: 'Test with just a spec',
spec: () => {
assert.ok(true);
}
});const { test, assert } = require('elmer-fudd');
test({
name: 'Unit testing a module',
unit: './path/to/double.js'
spec: (double) => {
assert.equal(double(2), 4);
}
});const { test, assert } = require('elmer-fudd');
test({
name: 'Unit testing a module',
unit: './path/to/unit.js',
mock: [
['.path', { fake: true }],
],
spec: (double) => {
assert.equal(double(2), 4);
}
});const { test, assert } = require('elmer-fudd');
test({
name: 'Using a spec object',
unit: './path/to/sum.js',
spec: [
{ given: [1, 2], expect: 3 },
{ given: [1, 2, 3], expect: 6 },
]
});assert
assert wraps node’s core assert.strict library so that failures can be grouped with tests. For detailed information see the docs. Here are a few examples to give you some ideas:
TODO examples that build...
mockFn
mockFn returns a mock function you can use in your specs. Here is how you might use a mock function.
const { mockFn } = require('elmer-fudd');
const fn = mockFn();
fn.returns(2);
fn(); // returns 2It is not a comprehensive solution, but if you need something more robust there is no reason you cannot use something like sinon instead. Mock functions have the following methods and properties:
fn.returns(value)makes the mock return a specific valuefn.implementation(fn)adds an implementation to the mockfn.calledWith(...args)returns true if the mock has been called with these argsfn.throws(err)when the mock is called, this error is thrownfn.resolves(value)the mock returns a promise that resolves this valuefn.rejects(err)the mock returns a promise that rejects with this errfn.reset()resets the mock functionfn.callsa getter that returns all the callsfn.counta getter that returns how many times the mock has been called
Tips & Tricks
Test driven?
You are allowed to mock the unit itself, which pared with "spec objects" creates a neat way you can write tests first without annoying failures. Then when you want to try the real unit you can comment out the test.
const { test, mockFn } = require('elmer-fudd')
test({
name: 'test first?',
unit: './my-busted-fn',
mock: [
['./my-busted-fn', mockFn().will([
{ given: [2], output: 'foo' },
{ given: [2, { extra: true }], output: { bar: 2 } },
])]
],
spec: [
{ given: [2], output: 'foo' },
{ given: [2, { extra: true }], output: { bar: 2 } }
],
})