Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to return fake data from spy.on(obj, 'funcName') when called ?

I don't know is there any function or not! Please let me know is it possible?

Something like that:

spy(obj, 'funcName').and.returnValue(5); // spy will return a fake data when 'funcName'called.

Well I am using mocha, chai-spies

like image 817
narainsagar Avatar asked Mar 05 '16 09:03

narainsagar


2 Answers

Instead of a spy, look at using a stub for this.

Per the docs:

Test stubs are functions (spies) with pre-programmed behavior. They support the full test spy API in addition to methods which can be used to alter the stub’s behavior.

Stubs have a "returns" method for doing what you're looking for.

var stub = sinon.stub();

stub.returns(54)

stub(); // 54
like image 171
DILP Avatar answered Nov 10 '22 18:11

DILP


Looks like they added a chai.spy.returns function to do just that, but the API seems a little weird to me. I installed the lastest code from their master branch and did some playing around. Here's what I experimented with:

var chai = require('chai'),
    spies = require('chai-spies');

chai.use(spies);
var expect = chai.expect;
var obj = null;

describe('funcName', function() {

  beforeEach(function() {
    obj = {
      funcName: function() {
        return true;
      }
    }
  });

  // PASSES
  it('returns true by default', function() {
    expect(obj.funcName()).to.be.true
  });

  // PASSES
  it('returns false after being set to a spy', function() {
    var spyFunction = chai.spy.returns(false);
    obj.funcName = spyFunction;
    expect(obj.funcName()).to.be.false
  });

  // FAILS
  it('returns false after being altered by a spy', function() {
    chai.spy.on(obj, 'funcName').returns(false);
    expect(obj.funcName()).to.be.false
  });

});

The output from running those tests is:

funcName
  ✓ returns true by default
  ✓ returns false after being set to a spy
  1) returns false after being altered by a spy


2 passing (14ms)
1 failing

1) funcName returns false after being altered by a spy:
   TypeError: Object #<Object> has no method 'returns'
    at Context.<anonymous> (test.js:31:34)

So it appears they want you to instantiate a spy object with a return value and then replace the funcName function on obj with it. You aren't able to spy on a function and set its return value in one fell swoop.

Furthermore, that functionality was added in October, 2015 and they have not published a new release since then. My recommendation would be to use a more mature library like Sinon.js for spies and stubs. You can use their Stub API to alter the return value of a function:

sinon.stub(obj, 'funcName').returns(5);

The Stub API affords many more ways to alter the behavior of a function, even going so far as to allow you to replace it with an entirely custom function:

var func = function() {...}

sinon.stub(obj, 'funcName', func);
like image 1
Nathan Thompson Avatar answered Nov 10 '22 17:11

Nathan Thompson