187

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

3 回答 3

275

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:

于 2013-04-25T06:45:52.397 回答
12

你也可以$provide用来创建一个间谍。并模拟使用and.returnValues而不是and.returnValue传入参数化数据。

根据 Jasmine 文档:通过将间谍与 链接起来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                
        }));
});
于 2016-11-15T06:17:33.567 回答
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 中指定的相同,就可以修改该函数内部所做的事情。

于 2020-02-04T19:02:09.573 回答