Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Spying on a function referenced from object doesn't work when this function was called indirectly #1083

Closed
shamansir opened this Issue Mar 27, 2016 · 4 comments

Comments

Projects
None yet
4 participants
@shamansir
Copy link

shamansir commented Mar 27, 2016

var foo = (function() {

    function bar(a) {
        console.log(a);
    }

    function callBarWith(a) {
        bar(a);
    }

    return {
        bar: bar,
        callBarWith: callBarWith
    }
})();

var barSpy = spyOn(foo, 'bar').and.callThrough();
//var barSpy = jasmine.createSpy('bar', foo.bar).and.callThrough();
foo.callBarWith(42);
expect(barSpy).toHaveBeenCalled();
expect(barSpy).toHaveBeenCalledWith(42);

both variants of creating a spy doesn't work for jasmine v2.4.1

both result in:

  • Expected spy bar to have been called.
  • Expected spy bar to have been called with [ 42 ] but it was never called.

Though following the console report, bar reference was actually called with '42' and logged the call.

If I replace foo.callBarWith(42) with foo.bar(42), everything works.

@shamansir

This comment has been minimized.

Copy link
Author

shamansir commented Mar 27, 2016

Changing it to one of these variants also helps, though:

var foo = (function() {

    var obj = {};

    obj.bar = function(a) {
        console.log(a);
    }

    obj.callBarWith = function(a) {
        obj.bar(a);
    }

    return obj;

})();
var foo = (function() {

    function MyObject() {};

    MyObject.prototype.bar = function(a) {
        console.log(a);
    }

    MyObject.prototype.callBarWith = function(a) {
        this.bar(a);
    }

    return new MyObject();

})();

but that looks like changing code to make tests pass.

@Gerg

This comment has been minimized.

Copy link
Contributor

Gerg commented Mar 29, 2016

Jasmine spies will only replace the function on the returned object. The callBarWith function will still have a handle on the original function. It should work if you call this.bar in callBarWith (even without modifying the prototype).

Thanks for using Jasmine!

@Gerg Gerg closed this Mar 29, 2016

@jackson-sandland

This comment has been minimized.

Copy link

jackson-sandland commented Apr 11, 2018

What is the rationale behind needing all the workaround to get spies to work as the community believes they should? When we are testing, and we create a spy, and we indicate a desire to spy on a given method, the spy should be able to listen for the same method that we called when we console.log in that method to test whether or not the spy is being called...which it is, except jasmine can't figure that out.

@slackersoft

This comment has been minimized.

Copy link
Member

slackersoft commented Apr 12, 2018

Unfortunately Javascript just doesn't work this way. If you've saved off a reference to the original function, Jasmine can do whatever it wants to the object you grabbed the function from, but it won't change your local variable reference to the original function. You probably don't want that anyways, as that would imply that any Javascript code running in the same process as your Javascript code can modify any of your local variables it wants to without your consent.

An example:

var foo = {
  bar: function() {
    console.log('original');
  }
};

var doThings = (function() {
  // save off a reference to the current function stored at foo.bar
  var myBar = foo.bar;

  return function() {
    myBar();
  }
})();

// replace the function stored at foo.bar
foo.bar = function() {
  console.log('replacement');
};

doThings();
> original

foo.bar();
> replacement

The Jasmine spy is installed similar to the replacement part of this example, so it is similarly unable to modify the saved off local variable reference.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.