I am currently testing a module in isolation using proxquire to overwrite a require of this module.
Overwriting a path of a require works fine with proxyquire. For example:
var bar = require('./bar');
But can you use proxyquire also to overwrite just a specific function of a module which is required in the module to test? So something like:
var bar = require('./foo').bar();
I need to stay at proxyquire for this since I am using it for mocking a http-request happening in another layer of the architecture. But in case of the test I need to mock the time for "now" in the module as well.
So currently I have this:
var uraStub = sendMockRequest(paramListOfCheckin, queryList);
var setNowStub = function(){ return 1425998221000; };
var checkin = proxyquire('../src/logic/logicHandlerModules/checkin', {
'../../persistence/ura' : uraStub,
'./checkin.setNow' : setNowStub
});
checkin.checkin(...)
The implementation of setNow is:
var setNow = function(){
return new Date().getTime();
};
var checkin = function (...) {
var now = require('./checkin').setNow();
Obviousley './checkin.setNow' : setNowStub in proxyquire doesn't work, since this is the wrong path. But using './checkin'.setNow() : setNowStub also doesn't work because of wrong syntaxis in the object-definition.
Any suggestions?
Thanks in advance!
What you are looking for is the noCallThru() and callThru() methods. https://github.com/thlorenz/proxyquire#preventing-call-thru-to-original-dependency
By default proxyRequire will call through to the mocked dependency which will allow you to pick the methods that you want to overwrite with your own custom function.
So if a dependency in the path '../foo' has a method bar() and fooBar() you would be able to mock out just bar by doing.
proxyquire.callThru();
var fooFunc = proxyquire('../foo', {
bar: () => return 'bar'
})
Now bar() will hit your custom overwritten funtion while fooBar() will be called as normal.
Related
I want to extend a current Node.js module with some global config setting being configured once without breaking current usages of this module.
This is the signature of the module:
const myFunction = function(someOptions) { ... };
module.exports = myFunction;
Usage is
const myFunction = require('myfunction');
const result = myFunction(options);
Now I want to set some options on application startup to be used by the module myfunction whenever being required without breaking current usages of the module myfunction.
If possible, I want to avoid using Node.js global.
Functions in JavaScript are just objects, so you can give them properties. This is a little hacky, but it could certainly work for you:
// greeter.js
function sayHello() {
const message = sayHello.message || "Hi";
console.log(message);
}
module.exports = sayHello;
You can now set the config of this function globally as follows:
const sayHello = require("./greeter.js");
sayHello.message = "S'up dawg";
Any subsequent calls to sayHello() after the code above is executed will use the overridden message. This works because calls to require() are cached, so each time you require(./greeter.js); you're getting back exactly the same function object.
From a performance perspective, is there any difference between invoking code by wrapping it in a function and then exporting it:
function doSomething () {
// doing something here
}
module.exports = doSomething();
And just requiring it without any exports? like this:
myModule.js
// Code doing something
file that requires the module:
var doSomething = require('./myModule');
And if the purpose of the code inside the module is to run just once, do I need to store it in a variable?
If you don't need the return value of that function, then you don't have to store it in a variable.
The difference with:
function doSomething () {
// doing something here
}
module.exports = doSomething();
and using:
var x = require('module');
var y = require('module');
vs.
function doSomething () {
// doing something here
}
module.exports = doSomething;
and using:
var x = require('module')();
var y = require('module')();
is that in the first case, the function will be run only once, while in the second case the function will be run twice.
The difference is that if you just include it without module.exports, then the code will execute immediately but be private to the module. You can only access the data if you export it somehow, with module.exports. It can be either a function or a Javascript Object. Essentially, you can view everything within the module as being completely hidden from everything else in your application.
The only shortcut that I know of is for JSON files. If you look here: Module.exports vs plain json for config files, you can see that you can require('file.json') and it will replace the contents of the json file with a Javascript object that you can then use in your application.
How do other node developers who use sinon mock out constructor calls within their unit tests? For example, suppose I have some function foo
function foo() {
var dependency = new Dependency(args);
// do stuff with dependency
}
exports.module.foo = foo;
and in a separate test file I have some test in which I want to verify what the Dependency constructor is called with (args), and I need to control what it returns
it('should call Dependency constructor with bar', function() {
var foo = require('myModule').foo
var DependencyMock; //code to make the mock
foo();
expect(DependencyMock.calledWith(bar)).to.equal(true);
});
The problem is that sinon can only mock functions attached to an object, so we have to attach the constructor to an object before it can be mocked.
What I've been doing is just making an object to attach the constructor to in the module making the constructor call, calling the constructor as a method of that object, then exporting the object to use it in tests:
var Dependency = require('path/to/dependency');
var namespace = {
Dependency: Dependency
}
function foo() {
var dependency = new namespace.Dependency(args);
// do stuff with dependency
}
exports.moduole.foo = foo;
exports.module.namespace = namespace;
testfile:
it('should call Dependency constructor with bar', function() {
var foo = require('myModule').foo;
var namespace = require('myModule').namespace;
var DependencyMock = sinon.mock(namespace, 'Dependency').returns(0);
foo();
expect(DependencyMock.calledWith(bar)).to.equal(true);
});
This works, but it feels really clunky to expose an object on my module just for the sake of testing it.
Any tips?
I think it's worth asking why you'd want to mock a constructor of a dependency instead of injecting that dependency?
Consider your example code:
// in "foo.js"
function foo() {
var dependency = new Dependency(args);
// do stuff with dependency
}
exports.module.foo = foo;
If Dependency is required for foo to work you can inject it as an argument of foo:
// in "foo.js"
function foo(dependency) {
// do stuff with dependency
}
exports.module.foo = foo;
// in "bar.js"
var foo = require('./foo.js')(new Dependency(args));
With this change it's now trivial to inject any Test Double in your tests (to find out more about JavaScript Test Doubles have a look at my article on the subject).
This approach makes the dependencies of your function/module explicit, but requires you to wire them up at some point (here: require('./foo.js')(new Dependency(args));).
If you didn't want to wire things up manually there's another approach you can take using rewire and replacing constructor with factory method:
// in "dependency.js"
module.exports= function(args) {
return new Dependency(args);
}
// in "foo.js"
var dependency = require('./dependency');
function foo() {
var dep = dependency(args);
// do stuff with dependency
}
exports.module.foo = foo;
and in your test:
var rewire = require("rewire"),
foo = rewire("../lib/foo.js");
it('should call dependency... ', function() {
foo.__set__("dependency", /* some spy */ );
foo();
});
Hope this helps!
Jan
I used a workaround for this:
// Keep a reference to your dependancy class.
const dependencyClass = Dependency;
let item = new Dependency();
// Replace class with a stub.(optionally return an item.
Dependency = sinon.stub(Dependency, 'constructor').returns(item);
// Call your code that you expect the class constructor to be called.
foo();
assert.isTrue(Dependency.calledWithNew());
assert.equal(1, Dependency.callCount);
// Restore class reference.
Dependency = dependencyClass;
Additionally, in the above case, an item is returned, so the user can have access to the dependency for further testing.
eg.
assert.equal(item.someValue, 10);
You can have other problems using this, eg defined properties will no longer be available for the class.
I agree with Jan Molek, use this in case you cannot change the code.
Not tried, but this could work: stub the constructor function of Dependency and let it return a mock.
var constructor = sinon.stub(Dependency.prototype, "constructor");
constructor.returns(sinon.mock(Dependency));
I encountered a similar problem with modules that expose functions rather than objects - this was my solution. Just putting this here as another way to go about tackling the issue but I must say solving the problem via better design, as Jan Molak suggested, seems like a better approach.
I'm trying to spy on dependencies in a Node.js module from within a Jasmine spec, and I'm encountering some weird behaviour.
Jasmine spies on a method that resides in an object exposed by the exports object in the module. When I call the spied-on method in the module using
exports.umap()
the spy detects it. But when I call it in the module using a variable name I assigned to the same method
var umap = exports.umap
umap()
the spy doesn't detect it.
This seems weird to me given that var umap refers to the same method as exports.umap. Anyone have any ideas why this is? Code below.
(The whole reason I'm doing this is that I want to stub my module's dependencies without the need to design the module as a class and use dependency injection.)
// mapper.js
exports.umap = require('underscore').map;
var umap = exports.umap;
function map () {
return exports.umap([1,2,3], function(el) {console.log(el);return el * 2});
// umap() goes unnoticed by the spy
// return umap([1,2,3], function(el) {console.log(el);return el * 2});
}
exports.map = map;
.
// mapper_spec.js
var mapper = require ('../../lib/mapper');
var map = mapper.map;
describe('mapper', function() {
describe('map', function() {
it('calls umap', function() {
var mapped;
spyOn(mapper, 'umap').and.callThrough();
mapped = mapper.map();
expect(mapper.umap).toHaveBeenCalled();
expect(mapped).toEqual([2,4,6]);
});
});
});
UPDATE
I'm still curious about this issue, however https://www.npmjs.org/package/proxyquire made my whole "spying-on-things-attached-to-export-object" strategy moot.
Writing the simplest module we could, we write into hello.js:
var hello = function(){
console.log('hello');
};
exports = hello; \\ Doesn't work on Amazon EC2 Ubuntu Instance nor Windows Powershell
I run Node and require the module
var hello = require('./hello');
hello;
and an empty array {} gets returned when I'm supposed to get [Function].
I tried replacing exports with module.exports, but this doesn't work on my Windows Powershell. It does work on my Amazon EC2 Ubuntu Instance, so why doesn't exports work? Has the API changed? And what could possibly be happening with Powershell that neither of these work?
I know Windows isn't the most desirable development environment, but I can't get my head around such a simple mishap.
EDIT
exporting with ES6 is a little nicer
export const hello = function(){
console.log('hello');
};
importing will look like
import {hello} from './file';
Original answer
You'll want to use module.exports
var hello = function(){
console.log('hello');
};
module.exports = hello;
If just exporting one thing, I'll usually do it all in one line
var hello = module.exports = function() {
console.log('hello');
};
Extras
If you use a named function, in the event an error occurs in your code, your stack trace will look a lot nicer. Here's the way I would write it
// use a named function ↓
var hello = module.exports = function hello() {
console.log("hello");
};
Now instead of showing anonymous for the function name in the stack trace, it will show you hello. This makes finding bugs so much easier.
I use this pattern everywhere so that I can debug code easily. Here's another example
// event listeners ↓
mystream.on("end", function onEnd() {
console.log("mystream ended");
};
// callbacks ↓
Pokemon.where({name: "Metapod"}, function pokemonWhere(err, result) {
// do stuff
});
If you want to export multiple things, you can use exports directly, but you must provide a key
// lib/foobar.js
exports.foo = function foo() {
console.log("hello foo!");
};
exports.bar = function bar() {
console.log("hello bar!");
};
Now when you use that file
var foobar = require("./lib/foobar");
foobar.foo(); // hello foo!
foobar.bar(); // hello bar!
As a final bonus, I'll show you how you can rewrite that foobar.js by exporting a single object but still getting the same behavior
// lib/foobar.js
module.exports = {
foo: function foo() {
console.log("hello foo!");
},
bar: function bar() {
console.log("hello bar!");
}
};
// works the same as before!
This allows you to write modules in whichever way is best suited for that particular module. Yay!
The reason exports is not working is because of the reference conflict. The top variable in each file is module which has a property module.exports. When the module is loaded new variable is created in the background. Something like this happens:
var exports = module.exports;
Obviously exports is a reference to module.exports, but doing
exports = function(){};
forces exports variable to point at function object - it does not change module.exports. It's like doing:
var TEST = { foo: 1 };
var foo = TEST.foo;
foo = "bar";
console.log(TEST.foo);
// 1
Common practice is to do:
module.exports = exports = function() { ... };
I have no idea why it doesn't work under Windows Powershell. To be honest I'm not even sure what that is. :) Can't you just use native command prompt?