Sinon function stubbing: How to call "own" function inside module - node.js

I am writing some unit tests for node.js code and I use Sinon to stub function calls via
var myFunction = sinon.stub(nodeModule, 'myFunction');
myFunction.returns('mock answer');
The nodeModule would look like this
module.exports = {
myFunction: myFunction,
anotherF: anotherF
}
function myFunction() {
}
function anotherF() {
myFunction();
}
Mocking works obviously for use cases like nodeModule.myFunction(), but I am wondering how can I mock the myFunction() call inside anotherF() when called with nodeModule.anotherF()?

You can refactor your module a little. Like this.
var service = {
myFunction: myFunction,
anotherFunction: anotherFunction
}
module.exports = service;
function myFunction(){};
function anotherFunction() {
service.myFunction(); //calls whatever there is right now
}

Related

Failing to mock declared functions with jest.spyOn

I'm under the impression that jest.spyOn.mockImplementationOnce can mock a function as long as it is implemented as a function expression, but might fail to mock when the function is written as a function declaration. Why is it behaving like that?
I have one TS file in the folder */this_works with the following code:
export function myFunction() {
return myOtherFunction();
}
export const myOtherFunction = function() {
return 'something';
};
And then another TS file in the folder */this_doesnt with the following code:
export function myFunction() {
return myOtherFunction();
}
export function myOtherFunction() {
return 'something';
}
The only difference between them is that myOtherFunction is either a function declaration or a function expression.
Both files are submitted to the same test with jest.
import * as myModule from '../index';
describe('myFunction', () => {
it('does something', () => {
jest
.spyOn(myModule, 'myOtherFunction')
.mockImplementationOnce(
function() {
return 'hello jest';
},
);
const result = myModule.myFunction();
expect(result).toEqual('hello jest');
});
});
All code can be found at my playground repo's folder
The result is that the function expression is mocked and the test passes, while the function declaration is not mocked and the test fails.
Anecdotally, this seems to only happen if the function being mocked is not being called directly, instead it is being called by another function. When the declared function gets called directly, the test passes.
I would like to understand why that is so I can write better tests.

How to mock methods for writing unit tests in nodejs [duplicate]

I can't figure out a way to stub a function called from within the same module this function is defined (the stub does not seem to work). Here's an example:
myModule.js:
'use strict'
function foo () {
return 'foo'
}
exports.foo = foo
function bar () {
return foo()
}
exports.bar = bar
myModule.test.js:
'use strict'
const chai = require('chai')
const sinon = require('sinon')
chai.should()
const myModule = require('./myModule')
describe('myModule', () => {
describe('bar', () => {
it('should return foo', () => {
myModule.bar().should.equal('foo') // succeeds
})
describe('when stubbed', () => {
before(() => {
sinon.stub(myModule, 'foo').returns('foo2') // this stub seems ignored
})
it('should return foo2', () => {
myModule.bar().should.equal('foo2') // fails
})
})
})
})
This reminds me of Java static functions which are not stubbable (almost).
Any idea how to achieve what I'm trying to do? I know that extracting foo in a different module will work, but that's not what I'm trying to do here. I'm also aware that invoking foo in the bar method with the keyword this will also work, I'm puzzled toward the use of ̀this in this context (since I'm not using OOP).
I just tested this. And it works like charm.
'use strict'
function foo () {
return 'foo';
}
exports.foo = foo;
function bar () {
return exports.foo(); // <--- notice
}
exports.bar = bar;
Explanation
when you do sinon.stub(myModule, 'foo').returns('foo2') then sinon stubs the exported object's foo not the actually foo function from inside your myModule.js ... as you must know, foo is in accessible from outside the module. So when you set exports.foo, the exported object exports.foo stores the ref of foo. and when you call sinon.stub(myModule, 'foo').returns('foo2'), sinon will stub exports.foo and not the actual foo
Hope this makes sense!
I was a bit wary of using exports since it's a bit magical (for instance when you're coding in Typescript, you never use it directly), so I'd like to propose an alternate solution, which still requires modifying the source code unfortunately, and which is simply to wrap the function to be stubbed into an object:
export const fooWrapper = {
foo() {...}
}
function bar () {
return fooWrapper.foo()
}
And sinon.stub(fooWrapper, 'foo'). It's a bit a shame having to wrap like that only for testing, but at least it's explicit and type safe in Typescript (contrary to to exports which is typed any).

node.js call function inside function class object

i have very good js background but i am new to node.js
i dont undersand why simple class object function is not calling
function functions () {
function test () {
console.log("function ok");
function test2 () {
console.log("function inside function is ok");
}
return {
test2 : test2
};
}
return {
test : test
};
}
var test_function = new functions();
functions.test.test2();
i get error
TypeError: Cannot read property 'test2' of undefined
thanks
Try calling test_function.test().test2(). You need to invoke test() before you can invoke test2(). Also, in your example you correctly invoked functions() and assigned it to test_function, but then you did not do anything with it.
Call it like this:
var test_function = new functions();
test_function.test().test2();

Node modules usage error

Ive node moudle which i need to export two functions and get to both of the function a parameter arg1,I try with the following I got error,what am I doing wrong here ?
UPDATE
Ive two method inside module
1. I need to expose it outside and to call it explicit from other
module with parameter
like
require('./controller/module')(functionName1)(parameter);
another function(functionName2) in this module which I need to call it explicit with two parameter ,how should I do it right?
It is not very clear what you want to do, but i think you want something like that:
module.exports = function (arg1) {
return {
server: function (params1) {
//do something with arg1 and params1
},
proc: function (params2) {
//do something with arg1 and params2
}
}
};
And using the module:
var arg1 = 'whatever'
var myMod = require('myMod')(arg1);
myMod.server();
myMod.proc();
Option 2
If i look at your new example
require('./controller/module')(functionName1)(parameter);
you need module that exports a function that returns another function (Higher Order Function).
So for example:
module.exports = function(functionName1) {
if(functionName1 === 'server'){
return function server(parameter){
//do your stuff here
}
}
if(functionName1 === 'proc'){
return function proc(parameter){
//do your stuff here
}
}
};

How to pass this to require() in NodeJS?

What's the best way to pass thisArg to a require()d module?
I want to do something like this:
index.js
function Main(arg) {
return {
auth: auth,
module: require('/some/module')
}
}
module.js
module.exports = {
someMethod: function() {...}
}
Then, in my code somewhere I call Main(), which returns the object.
So Main().auth exists, cool. But how do I access it from Main().module?
The thisArg in Main().module.someMethod() points to the module itself.. but I need the parent.
Is there any way to do this without using new keyword, functions and prototypes?
EDIT:
Thanks for all the answers guys! Some additional info:
Main() is the module what I wanna require() and use in my app. The "module" Main tries to import is actually just sub functionality of Main, it's just a part of code which I moved to a separate "module" to better organize the code.
So a better example would be:
function RestApi(param) {
return {
common_param: param,
commonFunc: function() {...}
endpoint1: require('/some/module'),
endpoint2: require('/some/module2'),
endpoint3: require('/some/module3')
}
}
And my app would use it like this:
RestApi = require('./RestApi')
RestApi().endpoint1.someHTTPCall(...)
But inside someHTTPCall(), both "common_param" and "commonFunc" should be accessible via thisArg, like this.commonFunc().
So this is kinda a general question, how do you merge multiple modules using require() properly, so "this" would point to the right object (i.e.: the parent)
I know this could be achieved using Function.prototype and inheritance, just would like to know if there is a simpler way.
The best I found so far is something like this:
var _ = require('lodash');
function Module(auth) {
this.auth = auth || {};
}
Module.prototype = {
endpoint1: function() { return _.extend(require('./endpoint1'),{auth: this.auth, commonFunc: commonFunc})}
}
function commonFunc() {...}
However, this is not ideal, since RestApi.endpoint1() would create a new the object on every call.
Is there a better way to handle this?
Thanks in advance!
Create own "require" module with auth param and allways use it.
project/module/require2.js
module.exports = function(path, auth){
if (!check(auth))
return null
return require(path)
}
You could change the module to return a function, like this:
// some/module.js
module.exports = function(mainModule) {
var main = mainModule;
return {
someMethod: function() {
main.doSomethingElse();
}
}
}
Then require it passing the main object:
function Main(arg) {
var main = {
auth: auth,
other: stuff,
};
main.module = require('/some/module')(main);
return main;
}

Resources