Unexpected assertion error of Sinon - javascript

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.

Related

How to write a function to disable console.log and can be required in other react file?

Below is my static.js file:
var Helper = {
console.log: function(){
},
Login: function(){
var name;
var password;
//rest of the code
}
}
module.exports = Helper;
And below is my test.js file:
var Helper = require('./static.js');
console.log("Test");
And I got some error from this line console.log: function(){} in static.js file.
What I want is nothing will show on terminal even I console.log('Test') because I write function(){} for console.log.
Is anything I did wrong?
Just overwrite console.log function in your script:
console.log = function() {};
Overwrite other log function too:
window.console.log = window.console.debug = window.console.info = window.console.error = function () {
return false;
}
I just figured out how to fix this problem.
I rewrite the function like below..
DisableConsole: function(DEBUG){
if(!DEBUG){
if(!window.console) window.console = {};
var methods = ["log", "debug", "warn", "info"];
for(var i=0;i<methods.length;i++){
console[methods[i]] = function(){};
}
}
}
and require this static.js file in my top component which mean every component under this main component will also include this static.js.
and call this function in the very beginning.
AppHelpers.DisableConsole(false);
You have this error because you're trying to create an object with a key console.log, but it is a syntax violation when using object literal syntax, because . dot is a special symbol.
Even if it worked, you wouldn't achieve what you want, since console.log is a global function and you are working with just a custom created object.
What you actually want to do is to silence the global function like this console.log = function() {};. Beware, however, that you won't be able to restore the old behaviour if you didn't save the original function: var oldConsoleLog = console.log.
There is also a module for it.

Using SinonJS stub (with rewire)

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();

How to unit test the following function in jasmine?

I have a following code:
angular
.module('testApp')
.factory('testDataService', function ($http) {
function testDataService(){
var self = this;
self.test = function(){
//do something
}
self.test1 = function(){
// do something
}
}
return new testDataService();
When I try to write a test case like
beforeEach(function(){
new testDataService();
});
It gives some error like:
> TypeError: '[object Object]' is not a constructor (evaluating 'new testDataService()')
There are numerous functions such as "test", "test1", etc.. inside testDataService. I am not able to test the remaining functions because the scope of the outer function is unreachable. I am not able to get the instance because of "var self=this"
Please help.
There is no need of new operator to create Object.
Please check this one
describe("\n\Testing factory", function () {
var factTestDataService;
beforeEach(inject(function (testDataService) {
factTestDataService= testDataService;
}))
it("factTestDataService test to defined",function(){
expect(factTestDataService.test()).toBeDefined()
})
it("factTestDataService test1 to defined",function(){
expect(factTestDataService.test1()).toBeDefined()
})
it("factTestDataService to defined",function(){
expect(factTestDataService).toBeDefined()
})
});
You need to inject testDataService factory and store it in local var.
Then you can use this one to access the method defined in that factory as you do in angular and can check with different Jasmine test method.
Your factory already returns a new instance of testDataService. There's no need for calling new. When you try to call new on an instance it throws the error you see.

Using Module pattern

I'm trying to use Module pattern where I'm getting the error "Cannot read property of undefined". This is because when I'm calling the module method with the module name, it is not able to get the module name and is getting it as undefined. Below is the code:
var myModule = (function(){
var myMethod;
myMethod = function() {
alert("callable");
};
return {
anotherMethod: function(){
myMethod();
}
};
}());
And below is how I'm calling the module method:
myModule.anotherMethod();
Please suggest if I'm missing anything.
Cheers,
AW
Based on this code working fine in a JSFiddle and the error, I believe you may not be properly including the file the JavaScript code is in before attempting to execute it. Here is some more information about the JavaScript module pattern.
<script>
var myModule =
(function(){
var myMethod;
myMethod = function() {
alert("callable");
};
return{
anotherMethod: function(){
myMethod();
}
};
}()
);
myModule.anotherMethod();
</script>
works perfectly fine and alerts "callable".

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