有什么方法可以根据参数修改Jasmine间谍?


146

我有一个函数要测试,该函数使用不同的参数两次调用外部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;
      }
    });
  });
});

Answers:


213

在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)

资源:


11
这是现在and.callFake- jasmine.github.io/2.2/... >
露西贝恩

我必须返回不同的Promise,所以返回的外观略有不同:return q.when(params [myParam]);。否则,这就是解决我的问题的地方。我理想的解决方案是更改“ and.returnValue”调用。
比尔·特纳2015年

7
感觉茉莉花应该有一个更好的声明方式。喜欢spyOn(fake, 'method').withArgs('abc').and.returnValue('Jane')spyOn(fake, 'method').withArgs('123').and.returnValue(98765)
jrharshath's

@jrharshath .withArgs
Jasmine

1
.withArgs并不是真的可用-我的意思是说这样的方法在编写测试时会有意义。
jrharshath's

9

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

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

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

这是正确的答案,因为测试应始终准确知道间谍将如何被调用,因此应仅用于returnValues支持多个调用
Schmuli

2
只是为了澄清akhouri的答案:仅当externalApi.get.and.returnValues('abc','123')it函数中调用时,此方法才有效 。否则,如果在其他地方设置了值列表,则它将永远无法工作,因为运行测试的顺序是不可预测的。实际上,测试不应依赖于执行顺序。
avi.elkharrat

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中指定的签名相同,就可以修改该函数在内部执行的操作。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.