I can't find a way to stub a function called from the same module where the function is defined (stubbing doesn't seem to work). Here is 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 (almost) not stubable.
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 also know that calling foo
using the keyword this
in the bar
method will also work, I'm not sure about using ̀this in this case
Confused (because I'm not using OOP).
P粉0990000442023-11-04 11:50:52
I'm a bit wary of using exports
since it's a bit magical (e.g. you never use it directly when coding in Typescript), so I wanted to propose an alternative solution, unfortunately The thing is that you still need to modify the source code, just wrap the function you want to stub into an object:
export const fooWrapper = { foo() {...} } function bar () { return fooWrapper.foo() }
and sinon.stub(fooWrapper, 'foo')
. It's a bit of a shame that you have to wrap it like this just for testing, but at least it's explicit and type-safe in Typescript (as opposed to exports
where the input is any
). < /p>
P粉7978557902023-11-04 00:12:56
I just tested this. It works like a charm.
'use strict' function foo () { return 'foo'; } exports.foo = foo; function bar () { return exports.foo(); // <--- notice } exports.bar = bar;
When you do sinon.stub(myModule, 'foo').returns('foo2')
, sinon
will stub the exported
object's foo
is not the actual foo
function in myModule.js
... As you must know, foo
is available from outside the module access. So when you set exports.foo
, the exported object exports.foo
stores the ref of foo
. When you call sinon.stub(myModule, 'foo').returns('foo2')
, sinon
will stub exports.foo
which is not the actual foo
Hope this makes sense!