Using object types with Jasmine's toHaveBeenCalledWith method

72,566

Solution 1

toHaveBeenCalledWith is a method of a spy. So you can only call them on spy like described in the docs:

// your class to test
var Klass = function () {
};

Klass.prototype.method = function (arg) {
  return arg;
};


//the test
describe("spy behavior", function() {

  it('should spy on an instance method of a Klass', function() {
    // create a new instance
    var obj = new Klass();
    //spy on the method
    spyOn(obj, 'method');
    //call the method with some arguments
    obj.method('foo argument');
    //test the method was called with the arguments
    expect(obj.method).toHaveBeenCalledWith('foo argument');   
    //test that the instance of the last called argument is string 
    expect(obj.method.calls.mostRecent().args[0] instanceof String).toBeTruthy();
  });

});

Solution 2

I've discovered an even cooler mechanism, using jasmine.any(), as I find taking the arguments apart by hand to be sub-optimal for legibility.

In CoffeeScript:

obj = {}
obj.method = (arg1, arg2) ->

describe "callback", ->

   it "should be called with 'world' as second argument", ->
     spyOn(obj, 'method')
     obj.method('hello', 'world')
     expect(obj.method).toHaveBeenCalledWith(jasmine.any(String), 'world')
Share:
72,566
screenm0nkey
Author by

screenm0nkey

Updated on July 05, 2022

Comments

  • screenm0nkey
    screenm0nkey almost 2 years

    I've just started using Jasmine so please forgive the newbie question but is it possible to test for object types when using toHaveBeenCalledWith?

    expect(object.method).toHaveBeenCalledWith(instanceof String);
    

    I know I could this but it's checking the return value rather than the argument.

    expect(k instanceof namespace.Klass).toBeTruthy();
    
  • stefan.s
    stefan.s about 12 years
    jasmine.any(Function) is handy, too
  • jds
    jds over 10 years
    Andreas, is there any reason you added .toBeTruthy()? It seems like that is unnecessary.
  • fncomp
    fncomp over 9 years
    Noticed that it also works inside on references. for example: expect(obj.method).toHaveBeenCalledWith({done: jasmine.any(Function)}). Very useful.
  • Mark Amery
    Mark Amery about 9 years
    @gwg expect(foo) without a matcher is a no-op; the line would do nothing without the toBeTruthy() call. See jsfiddle.net/2doafezv/2 for proof.
  • Mark Amery
    Mark Amery about 9 years
    This is out of date; obj.method.mostRecentCall needs to become obj.method.calls.mostRecent() in Jasmine 2.0. Also, using jasmine.any(), as described in the other answer, is clearer and cuter. Finally, this answer takes a while to get to the point; essentially everything you wrote besides expect(obj.method.mostRecentCall.args[0] instanceof String).toBeTruthy(); isn't really needed to explain yourself.
  • Fagner Brack
    Fagner Brack almost 8 years
    As of the time of this writing, Jasmine does not check for the same instance of new String('world') when using toHaveBeenCalledWith(...arguments). Click here to understand why that is important.
  • Admin
    Admin almost 7 years
    Had to check if a callback function was called, jasmin.any(Function) saved my life, thank you