120

I am trying to stub a method using sinon.js but I get the following error:

Uncaught TypeError: Attempted to wrap undefined property sample_pressure as function

I also went to this question (Stubbing and/or mocking a class in sinon.js?) and copied and pasted the code but I get the same error.

Here is my code:

Sensor = (function() {
  // A simple Sensor class

  // Constructor
  function Sensor(pressure) {
    this.pressure = pressure;
  }

  Sensor.prototype.sample_pressure = function() {
    return this.pressure;
  };

  return Sensor;

})();

// Doesn't work
var stub_sens = sinon.stub(Sensor, "sample_pressure").returns(0);

// Doesn't work
var stub_sens = sinon.stub(Sensor, "sample_pressure", function() {return 0});

// Never gets this far
console.log(stub_sens.sample_pressure());

Here is the jsFiddle (http://jsfiddle.net/pebreo/wyg5f/5/) for the above code, and the jsFiddle for the SO question that I mentioned (http://jsfiddle.net/pebreo/9mK5d/1/).

I made sure to include sinon in the External Resources in jsFiddle and even jQuery 1.9. What am I doing wrong?

Community
  • 1
  • 1
Paul
  • 2,409
  • 2
  • 26
  • 29

4 Answers4

178

Your code is attempting to stub a function on Sensor, but you have defined the function on Sensor.prototype.

sinon.stub(Sensor, "sample_pressure", function() {return 0})

is essentially the same as this:

Sensor["sample_pressure"] = function() {return 0};

but it is smart enough to see that Sensor["sample_pressure"] doesn't exist.

So what you would want to do is something like these:

// Stub the prototype's function so that there is a spy on any new instance
// of Sensor that is created. Kind of overkill.
sinon.stub(Sensor.prototype, "sample_pressure").returns(0);

var sensor = new Sensor();
console.log(sensor.sample_pressure());

or

// Stub the function on a single instance of 'Sensor'.
var sensor = new Sensor();
sinon.stub(sensor, "sample_pressure").returns(0);

console.log(sensor.sample_pressure());

or

// Create a whole fake instance of 'Sensor' with none of the class's logic.
var sensor = sinon.createStubInstance(Sensor);
console.log(sensor.sample_pressure());
loganfsmyth
  • 156,129
  • 30
  • 331
  • 251
  • 1
    Which thing is deprecated? – loganfsmyth Jul 22 '17 at 23:57
  • sinon.stub(Sensor, "sample_pressure", function() {return 0}) – danday74 Jul 23 '17 at 00:07
  • That's in my answer because the original question specifically asked about it. Given that my answer doesn't suggest it as the correct approach to begin with, I'm not sure what you're asking me to change. `.returns(0)` already does the same thing as `.callFake(() => 0)`. – loganfsmyth Jul 23 '17 at 00:39
  • 1
    It doesn't seem that `returns` is deprecated. http://sinonjs.org/releases/v3.0.0/stubs/. @danday74, please provide the reference. – allenhwkim Aug 07 '17 at 02:59
  • 3
    @danday74 `.stub` with a function as the third argument is removed: https://github.com/sinonjs/sinon/blob/master/lib/sinon/stub.js#L17 There is nothing wrong with `.returns` or `.callsFake`, so there is nothing wrong with this answer. – loganfsmyth Aug 08 '17 at 21:52
75

The top answer is deprecated. You should now use:

sinon.stub(YourClass.prototype, 'myMethod').callsFake(() => {
    return {}
})

Or for static methods:

sinon.stub(YourClass, 'myStaticMethod').callsFake(() => {
    return {}
})

Or for simple cases just use returns:

sinon.stub(YourClass.prototype, 'myMethod').returns({})

sinon.stub(YourClass, 'myStaticMethod').returns({})

Or if you want to stub a method for an instance:

const yourClassInstance = new YourClass();
sinon.stub(yourClassInstance, 'myMethod').returns({})
ndequeker
  • 7,932
  • 7
  • 61
  • 93
danday74
  • 52,471
  • 49
  • 232
  • 283
  • 6
    It would be great if you could mention the specific version for your said method when this was added to `sinonjs` i.e. `callsFake()` moreover, for the older versions how can this be deprecated? – aitchkhan Oct 26 '17 at 13:16
  • 3
    When using ES6 modules: I'm creating the stub of YourClass.get() in a test project. The test calls another module that imports YourClass. Will the module YourClass.get() respect the stub? If not, is there a solution? – Learner Feb 03 '18 at 06:14
  • 1
    Your solutions work for me. I wish if I give you more points :D Thanks. – Rubel hasan Jun 06 '18 at 23:22
6

I ran into the same error trying to mock a method of a CoffeeScript class using Sinon.

Given a class like this:

class MyClass
  myMethod: ->
    # do stuff ...

You can replace its method with a spy this way:

mySpy = sinon.spy(MyClass.prototype, "myMethod")

# ...

assert.ok(mySpy.called)

Just replace spy with stub or mock as needed.

Note that you'll need to replace assert.ok with whatever assertion your testing framework has.

Nathan Arthur
  • 8,287
  • 7
  • 55
  • 80
2

Thanks to @loganfsmyth for the tip. I was able to get the stub to work on an Ember class method like this:

sinon.stub(Foo.prototype.constructor, 'find').returns([foo, foo]);
expect(Foo.find()).to.have.length(2)
Scott Nedderman
  • 547
  • 5
  • 4
  • 3
    This is a comment. Starts with a thanks to another answer and ends with a duplication of its code. – michelpm Jul 25 '15 at 13:22
  • 5
    Doesn't look like a duplication -- here there is `Foo.prototype.constructor`, where as in original answer there is `Sensor.prototype`. Then again, `Foo.prototype.constructor` doesn't work for me. :) – shaunc Mar 24 '17 at 03:52