Open richardpj opened 8 years ago
can you provide a code sample?
I can.
'use strict';
const chai = require('chai');
const chaiAsPromised = require('chai-as-promised');
const lodash = require('lodash');
const sinon = require('sinon');
const sinonChai = require('sinon-chai');
describe('DataControl', function() {
chai.use(chaiAsPromised);
chai.use(sinonChai);
chai.should();
// Tested module
let dataControl;
// `dataControl`'s dependencies
let common;
let database;
let logger;
beforeEach(function() {
// Mocked dependencies // In `data-control.js`, they're declared like this:
common = sinon.stub(); // const common = require('common');
database = sinon.stub(); // const database = new common.DB();
logger = sinon.stub(); // const logger = new common.Logger();
// Tested module and its dependencies
dataControl = rewire('../../../../app/business/data-control', {
common,
database,
logger,
});
});
describe('someTestedFunction(foo, bar)', function() {
it('should do some stuff', function(done) {
// Teste function arguments
const foo = lodash.cloneDeep(fixtureFooGood);
const bar = lodash.cloneDeep(fixtureBarBad);
// Tested function
const result = someTestedFunction(foo, bar);
// Assertions
result.should.be.fulfilled.then(() => {
database.readStuff.should.have.been.calledWithExactly(foo);
logger.info.should.have.been.calledWithExactly(bar);
}).should.notify(done);
});
});
});
The idea here is that if you just common = rewire('common')
and then i.e.
common.__set__('DB', sinon.stub())
, then the common
module had an opportunity to run undesired code before we apply the stub.
Same thing with the database = new common.DB()
call. We would like to prevent these lines of code to even be run, since they're not part of our unit test.
Passing the stub definitions like this to rewire
would allow it to avoid running code that initialises a variable for which it already has a stub for. This is relevant for modules that run a lot of code directly when require
d. newrelic
comes to mind (adds instrumentation to DBs), but is not the only case.
At the very least we could have something like this for require
s, like proxyquire
does, but with rewire
's injected setters / getters too.
I know your reply is kind of outdated, but I agree with this; rewire
should allow injection before execution; e.g. rewire("path/to/my/script", {...keyValuePairsToOverride})
.
I think the simplest possible workaround is this is:
Suppose you have one file which is our "main"
in package.json:
// index.js
const toBeOverridden = require("stuff")
// do stuff
Change it to two files:
// auxiliary.js
const toBeOverridden = require("stuff")
module.exports = () => {
//do stuff
}
and
// index.js, our new "main" in package.json
const script = require("./auxiliary.js)
script()
Then, you can just unit test auxiliary.js
I am trying to test a node shell script (in a sense a self executing module). It would be great if mocks could be injected at/prior to rewire time for this purpose.