有没有办法根据参数修改Jasmine间谍?

时间:2013-04-24 17:22:36

标签: javascript unit-testing jasmine

我有一个函数我想测试哪个调用外部API方法两次,使用不同的参数。我想用Jasmine间谍模拟这个外部API,并根据参数返回不同的东西。在Jasmine有什么办法吗?我能想到的最好的是使用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;
      }
    });
  });
});

3 个答案:

答案 0 :(得分:156)

在Jasmine 3.0及以上版本中,您可以使用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);
  });
});

对于3.0之前的Jasmine版本callFake是正确的方法,但您可以使用对象来简化它以保存返回值

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]
    });
  });
});

根据Jasmine的版本,语法略有不同:

  • 1.3.1:.andCallFake(fn)
  • 2.0:.and.callFake(fn)

资源:

答案 1 :(得分:7)

您还可以使用$provide创建间谍。并使用and.returnValues代替and.returnValue进行模拟以传递参数化数据。

  

根据Jasmine docs:通过使用and.returnValues链接间谍,对该函数的所有调用都将按顺序返回特定值,直到它到达返回值列表的末尾,指出它将为所有后续调用返回undefined。

describe('my fn', () => {
    beforeEach(module($provide => {
        $provide.value('externalApi', jasmine.createSpyObj('externalApi', ['get']));
    }));

        it('get userName and Id', inject((externalApi) => {
            // Given
            externalApi.get.and.returnValues('abc','123');

            // When
            //insert your condition

            // Then
            // insert the expectation                
        }));
});

答案 2 :(得分:0)

就我而言,我有一个正在测试的组件,并且在其构造函数中,有一个配置服务,该服务带有名为 getAppConfigValue 的方法,该方法被调用两次,每次使用不同的参数:

constructor(private configSvc: ConfigService) {
  this.configSvc.getAppConfigValue('a_string');
  this.configSvc.getAppConfigValue('another_string');
}

在我的规范中,我像这样在TestBed中提供了ConfigService:

{
  provide: ConfigService,
  useValue: {
    getAppConfigValue: (key: any): any {
      if (key === 'a_string) {
        return 'a_value';
      } else if (key === 'another_string') {
        return 'another_value';
      }
    }
  } as ConfigService
}

因此,只要 getAppConfigValue 的签名与实际ConfigService中指定的签名相同,就可以修改该函数在内部执行的操作。