Security News
cURL Project and Go Security Teams Reject CVSS as Broken
cURL and Go security teams are publicly rejecting CVSS as flawed for assessing vulnerabilities and are calling for more accurate, context-aware approaches.
breadboard
Advanced tools
Breadboard is an opinionated inversion of control container for Node.js applications.
require
is less than ideal.
require
calls. This approach is indeterministic, depending on various seemingly unrelated conditions around how the the module you want to mock was defined.require
ing.Breadboard will lazily require all your application's dependencies defined in package.json
, all Node native modules and all of your application's modules and store them in a dependencies
object. The object is exposed to your application's modules by calling the modules as functions, passing the dependencies as an argument. As such, your modules are expected to be wrapped in an extra function returning the desired export value, which Breadboard then calls on application start.
npm install breadboard
Consider this CommonJS module:
//startServer.js
const d = require('debug')('myApp');
const createServer = require('./lib/createServer');
module.exports = () => {
const server = createServer();
server.listen(80, () => {
d('Server listening on port 80');
});
return server;
};
The Breadboard equivalent would be:
//startServer.js
// wrap module in factory function
module.exports = ({ // destructure dependencies to get the modules needed
debug,
'/lib/createServer': createServer
}) => {
// return the core functionality of the module as a function
return () => {
const server = createServer();
const d = debug('myApp');
server.listen(80, () => {
d('Server listening on port 80');
});
return server;
};
};
To start your application:
const breadboard = require('breadboard');
breadboard({
entry: '/index',
containerRoot: 'app',
initialState: {
arbitrary: 'state data'
},
blacklist: ['newrelic']
}).then((entryPointReturnValue, dependencies) => {
console.log('Application started', entryPointReturnValue, dependencies);
});
Take a look at examples/kitchen
. To run, npm install
then npm start
.
Module keys in a Breadboard app are static, ie. are always relative to the container's root folder, starting with /
, and always using /
as path separators, no matter the platform. Consider these example module keys:
/lib/getUser
/middleware/getUser
/logger
Keys for native Node.js modules and 3rd party modules remain the same as if you were using require
.
Breadboard also loads all JSON files. To access them, append .json
to the end of the key, eg. /data/userPasswords.json
.
Node.js ~4.4
breadboard(options)
Returns a promise chained to the return value of your application's entry point, which might be another promise or a concrete value.
options
options.entry
(String | Function<Object>)Module key for the entry point of the application.
Will be called as the entry point module, with resolved dependencies as the argument.
options.containerRoot
(String)Path relative to the current working directory, from which all module keys will be resolved
options.initialState
(Object)The argument the entry
function will be called with.
options.blacklist
(Array<String>)List of modules from your package.json
which you wish Breadboard not to load. If you want to defer a require
call to a 3rd party module, put it in the blacklist
and require
manually in your code.
options.substitutes
(Object)A Breadboard module-key to module mapping to indicate which modules you want to substitute across the whole application with your custom implementation. Useful when testing integration of multiple modules. You could substitute eg. a database connector with a stub to remove a running database as a dependency of your tests.
In tests require your Breadboard modules as if they were CommonJS modules. You can then supply your own stubs and spies as test doubles. Consider the following example:
/index
module.exports = (deps) => {
return () => {
const {
'/widgets/createDough': createDough,
'/pasta/createPapardelle': createPapardelle,
'debug': debug
} = deps;
const d = debug('pasta');
d(createPapardelle(createDough()));
};
};
/index
import { expect } from 'chai';
import mainFactory from '../../app/index';
import sinon from 'sinon';
describe('Main', () => {
const sandbox = sinon.sandbox.create();
const debugSpy = sandbox.spy();
const mockDough = 'dough';
const mockDependencies = {
debug: sandbox.stub().returns(debugSpy),
'/widgets/createDough': sandbox.stub().returns(mockDough),
'/pasta/createPapardelle': sandbox.spy()
};
let main;
beforeEach(() => {
main = mainFactory(mockDependencies);
});
afterEach(() => {
sandbox.reset();
});
it('calls debug', () => {
main();
expect(mockDependencies.debug.calledOnce).to.be.true;
});
it('calls createDough', () => {
main();
expect(mockDependencies['/widgets/createDough'].calledOnce).to.be.true;
});
it('calls createPapardelle with createDough return value', () => {
main();
expect(mockDependencies['/pasta/createPapardelle'].calledWith(mockDough)).to.be.true;
});
});
autoMock
autoMock
automatically replaces every dependency of a given Breadboard module with a Sinon.JS stub.
autoMock
APIautoMock(factory, options)
factory
(Function)The Breadboard factory function to build the subject to test.
options
(Object)options.mocks
(Object)A Breadboard module-key to module mapping to indicate which modules you want to mock manually.
subject
The module returned by factory
.
deps
The mock dependencies injected into subject
.
sandbox
Instance of a Sinon.JS sandbox.
autoMock
example/index
module.exports = (deps) => {
return function main() {
const {
'/widgets/createDough': createDough,
'/pasta/createPapardelle': createPapardelle,
'debug': debug
} = deps;
const d = debug('pasta');
d(createPapardelle(createDough()));
};
};
/index
import { expect } from 'chai';
import mainFactory from '../../app/index';
import autoMock from 'breadboard/lib/autoMock';
const mockDough = 'dough';
const {subject: main, sandbox, deps} = autoMock(mainFactory);
const debugSpy = sandbox.spy();
deps.debug.returns(debugSpy);
deps['/widgets/createDough'].returns(mockDough);
describe('Main', () => {
afterEach(() => {
sandbox.reset();
});
it('calls debug', () => {
main();
expect(deps.debug.calledOnce).to.be.true;
});
it('calls createDough', () => {
main();
expect(deps['/widgets/createDough'].calledOnce).to.be.true;
});
it('calls createPapardelle with createDough return value', () => {
main();
expect(deps['/pasta/createPapardelle'].calledWith(mockDough)).to.be.true;
});
});
FAQs
Lightweight IOC container for Node.js
The npm package breadboard receives a total of 9 weekly downloads. As such, breadboard popularity was classified as not popular.
We found that breadboard demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
cURL and Go security teams are publicly rejecting CVSS as flawed for assessing vulnerabilities and are calling for more accurate, context-aware approaches.
Security News
Bun 1.2 enhances its JavaScript runtime with 90% Node.js compatibility, built-in S3 and Postgres support, HTML Imports, and faster, cloud-first performance.
Security News
Biden's executive order pushes for AI-driven cybersecurity, software supply chain transparency, and stronger protections for federal and open source systems.