Using SinonJS stub (with rewire) - javascript

I have a function:
var publish = function(a, b, c) {
main = a + getWriterName(b,c);
}
and getWriterName is another function:
var getWriterName = function(b,c) {
return 'Hello World';
}
I want to test the "publish" function but I do not want to run the "getWriterName" function while I am testing "publish". I feel like I stub getWriterName function because I don't want to run it everytime I test "publish", but how do I do that? I did something like:
var sandbox = sinon.sandbox.create();
sandbox.stub(getWriterName).returns('done');
But this gives me an error of
TypeError: Attempted to wrap undefined property undefined as function
What is wrong with my stubbing if I am in the write path?
Edit:
I am using rewire so would like solutions using rewire

This is how Sinon can be used with Rewire to stub a function. Rewire in this case is particularly useful if the stubbed function is private.
it('getWriteName always returns "Hello World"', function() {
var stub = sandbox.stub();
stub.returns('Hello World');
var unset = log.__set__('getWriterName', stub);
// your test and expectations here
unset();
// it's always good to restore the previous state
});

This solved my problem:
If my functions are in a file called main.js then firstly I'd rewire the file as:
var main = rewire('main');
Then to stub any other function being called in one function, in my case, when I had to stub getWriterName I'd do:
main.__set__('getWriterName', function(b, c) {
return 'Something Else'
}
and Finally after finishing using it, do
main.restore();

From sinon docs: "The sinon.sandbox.create(config) method is mostly an integration feature, and as an end-user of Sinon.JS you will probably not need it."
Normally you create a sinon stub with the syntax:
sinon.stub(obj, 'property, function(){
//do something
}
Let's say that somewhere in your file you are exporting these two functions
//somefile.js
var publish = function(a, b, c) {
main = a + getWriterName(b,c);
}
var getWriterName = function(b,c) {
return 'Hello World';
}
exports.getWriterName = getWriterName;
exports.publish = publish;
Importing them in your tests:
var someFile = require('./somefile.js');
And trying to stub out the method you'd like to:
sinon.stub(someFile, 'getWriterName', function(b, c) {
return 'done'
});
You'll find that this too won't work. This is because sinon can't actually stub out a method that has been required unless it can access it as a property of the file you required. In order for this to work, you'd need to be doing this:
//somefile.js
var getWriterName = function(b,c) {
return 'Hello World';
}
exports.getWriterName = getWriterName;
var publish = function(a, b, c) {
main = a + exports.getWriterName(b,c);
}
exports.publish = publish;
Now the getWriterName is accessible for stubbing out once you import the file with the functions into your tests. You'd do it just like the above example:
sinon.stub(someFile, 'getWriterName', function(b, c) {
return 'done'
});
And can undo it with:
someFile.getWriterName.restore();

Related

callThrough not working when creating spy using createSpyObj

It seems the and.callThrough does not actually run the original implementation, when the spy object is created using createSpyObj. As an example, let say I have an Angular service that has the following helper method:
user.service.ts:
class UserService {
getFullName(first: string, last: string): string {
return first + ' ' + last;
}
}
In the specs, I create a spy using createSpyObj:
user.service.specs.ts
const userServiceSpy = jasmine.createSpyObj<UserService>('UserService', ['getFullName']);
// ....
beforeEach(() => {
userServiceSpy.getFullName.and.callThought();
const test = userService.getFullName('test1', 'test2');
console.log(test); // < = = = = = ISSUE: test is undefined! WHY ???
});
How can I make the getFullName function run as implemented in the main class?
(I don't want to stub, or call a fake function, but somehow use the main function implementation when calling the getFullName).
I tried overwriting the function prototype with the original:
userServiceSpy.getFullName.prototype = UserService.prototype.getFullName;
Second attempt:
userServiceSpy.getFullName = UserService.prototyp.getFullName; // This is a compile error.
We need to use callFake and use the function implementation from the prototype as follows:
userServiceSpy.getFullName.and.callFake(UserService.prototype.getFullName);

Unexpected assertion error of Sinon

I'm quite new in usage of Sinon.
Suppose we have module ( named myModule.js ) definition :
//myModule.js
var _f2 = function() {
console.log('_f2 enter');
return {prop1:'var1'};
};
var f1 = function(){
var myVar1 = _f2();
console.log('_f2 called');
};
module.exports._f2 = _f2;
module.exports.f1 = f1;
And here is test for the module
var sinon = require('sinon');
var myModule = require('./myModule');
describe('test my module',function(){
var f2Spy ;
beforeEach(function(){
f2Spy = sinon.spy(myModule,'_f2');
});
afterEach(function(){
myModule._f2.restore();
});
it('call _f2',function(done){
myModule.f1();
sinon.assert.called(f2Spy);
done();
})
});
When running this test , I got assert error that _f2 was not called:
AssertError: expected _f2 to have been called at least once but was never called
But from log messages I can see that _f2 was called.
The question is : what cause to the error ? Thanks in advance
If you modify your module this way, then the test will pass:
var f1 = function(){
var myVar1 = exports._f2();
console.log('_f2 called');
};
(By the way, using exports in my code above is equivalent to using module.exports given the code you've shown.)
The problem with your original code is that there is no way for other regular JavaScript code to intercept direct calls to _f2 that are made inside your module. Sinon is regular JavaScript code, so it cannot intercept direct calls to _f2. If you make your call through the exports table, then there is an opportunity for Sinon to patch this table to intercept the call.

Synchrone issue readdir with singleton in Node.js

First app with Node.js, trying to make a file explore to get contents from them, within a singletoned class, but the order is not that i expected. Surely a knowledge missing from me, can you tell me why..
Singleton class :
var Singleton = (function()
{
var _instance = null;
return new function()
{
this.Instance = function()
{
if (_instance == null)
{
_instance = new Foo();
}
return _instance;
}
};
})();
The Foo class :
var Foo= function Foo()
{
this._filesDir= "./core/files/";
this._storedFiles = {};
this.method1();
console.log("call constructor");
};
Foo.prototype = {
method1: function()
{
console.log("call method1");
var that = this;
var c = 0;
fs.readdirSync(this._filesDir).forEach(function(fileName)
{
console.log("iterating file"+ c);
c++;
fs.readFile(that._filesDir + fileName, 'utf-8', function(err, content)
{
var clean_FileName = fileName.replace(".txt", "");
console.log( clean_fileName );
that._storedFiles[ clean_fileName ] = content;
});
});
},
method2: function( fileName )
{
console.log('call method2');
return ( fileName in this._storedFiles);
}
};
The calling :
console.log( Singleton.Instance().method2("myfile") );
In the directory, there is only this myfile.txt
But, the console displaying me that :
call method1
iterating file0
call constructor
call method2
false
GET /test 304 11ms
myfile
So my response is false and is this normal constructor called at the third position ? I need the class construct, store, and finally execute the method2(). What i'm doing bad ?
The root of your problem is that fs.readFile is asynchronous. method1 returns before you've read the contents of the file. A simple fix is to change it to fs.readFileSync.
The reason "call constructor" is third is because you invoke method1() first.
this.method1();
console.log("call constructor");
Everything in method1 gets run before console.log("call constructor") happens. You can simply swap the two if you want the order to be correct.
From a high-level, using synchronous calls (readdirSync, readFileSync) is usually a bad idea because they block Node from doing anything else while they're running. I would recommend studying callbacks, control flow, and the asynchronous nature of Node.js. There are lots of great tutorials out there.

Node.js double call to require()

//lib.js
var opt = 0
exports.set = function(arg) {
opt = arg
}
exports.prn = function() {
console.log(opt)
}
///prog.js
var lib = require('./lib')
var lib2 = require('./lib')
lib.set(222)
lib2.set(333)
lib.prn()
lib2.prn()
prog.js will output:
333
333
but I need it to output:
222
333
In ohter words, opt must be unique to variable lib and to variable lib2. How to achieve that?
That's because normally nodejs caches its modules which are got via require. You may use the following helper:
// RequireUncached.js
module.exports = function(module) {
delete require.cache[require.resolve(module)]
return require(module);
}
and the usage of the helper:
var requireUncached = require('RequireUncached.js');
requireUncached("./lib");
Have in mind that this approach is considered as bad practice and should not be used. I'll suggest to wrap your logic into a function, require the module and call the function. So, every time you get a new instance.
require will not load scripts multiple times, but always yield the same instance.
If you need different environments, make your module a constructor function that allows to be instantiated multiple times. Store opt on each object for that instead of in the (global) module scope.
// lib.js
module.exports = function constr() {
var opt = 0
this.set = function(arg) {
opt = arg
};
this.print = function() {
console.log(opt)
};
};
// prog.js
var lib = require('./lib'),
inst1 = new lib(),
inst2 = new lib();
/* or short:
var inst1 = new require('./lib')(),
inst2 = new require('./lib')(); */
inst1.set(222)
inst2.set(333)
inst1.print()
inst2.print()
The way the NodeJS module system works, the output is correct and your expectations contradict the design principle here.
Each module is loaded once and only once, and subsequent calls to require simply return the reference to the pre-existing module.
Maybe what you need to do is create a class you can create one or more instances of instead of using module-level globals.
Adding to Bergi's answer, You may also try it like
// prog.js
var lib = require('./lib')(),
lib2 = require('./lib')();
lib.set(222)
lib2.set(333)
lib.print()
lib2.print()
// lib.js
module.exports = function constr() {
var opt = 0
return { set : function(arg) {
opt = arg
},
print : function() {
console.log(opt)
}
}
};
Add this line as first line of your lib.js
delete require.cache[__filename]
now your module becomes in a separate namespace each time you require it.

How to write simple, extensible, modular Javascript

I need a mechanism whereby people can extend my base code with their own modules - but I'm struggling to come-up with a simple mechanism to do that.
Example: a function called 'test' which users can extend. Each user module is loaded after the original - so each one needs to build on the last (the order they're loaded should not matter or can be controlled by naming)
I started to play with something like this
var test = function() { // the master function
console.log("1");
}
var ltest = test; // module 1
var test = function() {
ltest();
console.log("2");
}
var ltest2 = test; // module 2
var test = function() {
ltest2();
console.log("3");
}
Then, when 'test' is called, it will run everyone's code (assuming no-one forgot their callback!!)
That works, but it relies on each module declaring it's own, unique 'callback' variable (ltest, ltest2) - if someone uses the same variable, we'll get a 'call stack exceeded' as those variables are global in scope...
Can anyone suggest a cleverer/better system - or point me to some examples of the same thing?
There's loads of material on inheritance but I don't want to create new things which extend the old one - I just want to extend the old one!!
p.s. taking the anonymous function stuff from the module pattern - I got this
var test = function() {
console.log("1");
}
(function() {
var oldtest = test;
test = function() {
oldtest();
console.log("2");
}
}())
(function() {
var oldtest = test;
test = function() {
oldtest();
console.log("3");
}
}())
Which is probably the simplest solution to my question - but not necessarily the best system to use (as it's dependant on the author to remember to callback the code - a dodgy module would break everything)
The Module Pattern is what you need.
In particular the 'Augmentation' or 'Loose Augmentation' patterns :
var MODULE = (function (my) {
var old_moduleMethod = my.moduleMethod;
my.moduleMethod = function () {
// method override, has access to old through old_moduleMethod...
};
return my;
}(MODULE || {}));
You could make a function like this
function extendFunction(fn, pre, post) {
return function () {
var arg = arguments;
if (pre) arg = pre.apply(this, arg); // call pre with arguments
arg = fn.apply(this, arg); // call fn with return of pre
if (post) arg = post.apply(this, arg); // call post with return of fn
return arg;
};
}
then extend as follows
var test = function () { // the master function
console.log("1");
};
test = extendFunction(
test, // function to extend
null, // thing to do first
function() {console.log("2");} // thing to do after
);
test = extendFunction(
test,
null,
function() {console.log("3");}
);
test(); // 1, 2, 3
This is very different to the normal meaning of "extend" though, where you give new properties to Objects or set up prototype chains, and to "module" which normally involves wrapping all your code in a function expression so that you don't pollute the namespace.

Categories

Resources