Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Stubbing method in same file using Sinon

I'm trying to unit test a function in a file while stubbing another function in the SAME file, but the mock is not being applied and the real method is being called. Here's an example:

// file: 'foo.js'

export function a() {
   // .....
}

export function b() { 
   let stuff = a(); // call a
   // ...do stuff
}

And my test:

import * as actions from 'foo';

const aStub = sinon.stub(actions, 'a').returns('mocked return');
actions.b(); // b() is executed, which calls a() instead of the expected aStub()
like image 857
Steven Musumeche Avatar asked Oct 04 '16 21:10

Steven Musumeche


People also ask

How do you stub a dependency of a module?

To stub a dependency (imported module) of a module under test you have to import it explicitly in your test and stub the desired method. For the stubbing to work, the stubbed method cannot be destructured, neither in the module under test nor in the test.

How do I reset my Sinon stub?

var stub = sinon. The original function can be restored by calling object. method. restore(); (or stub. restore(); ).


2 Answers

Some restructuring can make this work.

I've used commonJS syntax. Should work in the same way in ES6 as well.

foo.js

const factory = {
  a,
  b,
}
function a() {
  return 2;
}

function b() {
  return factory.a();
}

module.exports = factory;

test.js

const ser = require('./foo');
const sinon = require('sinon');

const aStub = sinon.stub(ser, 'a').returns('mocked return');
console.log(ser.b());
console.log(aStub.callCount);

Output

mocked return

1

like image 169
anoop Avatar answered Sep 19 '22 15:09

anoop


While the above does work, it's definitely a workaround as my linter was quick to inform.

I ended up separating modules and using proxyquire. This library allows you to easily substitute any / all exports with those of your choosing, sinon stub spy or mocks included. e.g. :

in b.js

export const fnB = () => 'hey there!';

in a.js

import { fbB } from 'b.js';
export const fnA = () => fbB();

in a.test.js

import { noCallThru } from 'proxyquire';
const proxyquireStrict = noCallThru();
const stubB = stub().returns('forced result');
const moduleA = proxyquireStrict('a.js', {
    'b.js' : { fnB: stubB }
}).fnA; 

console.log(fnA()); // 'forced result'
like image 42
benipsen Avatar answered Sep 17 '22 15:09

benipsen