Any way to modify Jasmine spies based on arguments?

jasmine, javascript, unit-testing

Solution

In Jasmine versions 3.0 and above you can use `withArgs`

describe('my fn', function() {
  it('gets user name and ID', function() {
    spyOn(externalApi, 'get')
      .withArgs('abc').and.returnValue('Jane')
      .withArgs('123').and.returnValue(98765);
  });
});

For Jasmine versions earlier than 3.0 `callFake` is the right way to go, but you can simplify it using an object to hold the return values

describe('my fn', function() {
  var params = {
    'abc': 'Jane', 
    '123': 98765
  }

  it('gets user name and ID', function() {
    spyOn(externalApi, 'get').and.callFake(function(myParam) {
     return params[myParam]
    });
  });
});

Depending on the version of Jasmine, the syntax is slightly different:

- 1.3.1: `.andCallFake(fn)`

- 2.0: `.and.callFake(fn)`

Resources:

- withArgs docs

- callFake docs

- andCallFake vs and.callFake

Problem

I have a function I'd like to test which calls an external API method twice, using different parameters. I'd like to mock this external API out with a Jasmine spy, and return different things based on the parameters. Is there any way to do this in Jasmine? The best I can come up with is a hack using andCallFake: ``` var functionToTest = function() { var userName = externalApi.get('abc'); var userId = externalApi.get('123'); }; describe('my fn', function() { it('gets user name and ID', function() { spyOn(externalApi, 'get').andCallFake(function(myParam) { if (myParam == 'abc') { return 'Jane'; } else if (myParam == '123') { return 98765; } }); }); }); ```

Original source

Related problems