Bất kỳ cách nào để sửa đổi gián điệp Jasmine dựa trên lập luận?


146

Tôi có một chức năng tôi muốn kiểm tra mà gọi một phương thức API bên ngoài hai lần, sử dụng các tham số khác nhau. Tôi muốn chế giễu API bên ngoài này bằng một gián điệp Jasmine và trả lại những thứ khác nhau dựa trên các tham số. Có cách nào để làm điều này trong Jasmine? Điều tốt nhất tôi có thể nghĩ ra là hack bằng cách sử dụng 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;
      }
    });
  });
});

Câu trả lời:


212

Trong phiên bản Jasmine 3.0 trở lên, bạn có thể sử dụng 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);
  });
});

Đối với các phiên bản Jasmine sớm hơn 3.0 callFakelà cách phù hợp, nhưng bạn có thể đơn giản hóa nó bằng cách sử dụng một đối tượng để giữ các giá trị trả về

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

Tùy thuộc vào phiên bản của Jasmine, cú pháp hơi khác nhau:

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

Tài nguyên:


11
Đây là bây giờ and.callFake- jasmine.github.io/2.2/ khăn >
Lucy Bain

Tôi đã phải trả lại những lời hứa khác nhau, vì vậy sự trở lại có vẻ hơi khác: return q.when (params [myParam]);. Mặt khác, đây là một giải pháp cho vấn đề của tôi. Giải pháp mơ ước của tôi sẽ là thay đổi các cuộc gọi "and.returnValue".
Bill Turner

7
cảm thấy như hoa nhài nên có một cách tốt hơn để tuyên bố điều này. Thích spyOn(fake, 'method').withArgs('abc').and.returnValue('Jane')spyOn(fake, 'method').withArgs('123').and.returnValue(98765).
jrharshath

@jrharshath .withArgskhông hoạt động với tôi trong hoa nhài 2.0
hemkaran_raghav

1
.withArgslà không thực sự có sẵn - tôi có nghĩa là một phương pháp như vậy sẽ có ý nghĩa khi viết bài kiểm tra.
jrharshath

9

Bạn cũng có thể sử dụng $provideđể tạo ra một điệp viên. Và giả sử dụng and.returnValuesthay vì and.returnValueđể truyền dữ liệu tham số.

Theo tài liệu của Jasmine: Bằng cách kết nối gián điệp với and.returnValues, tất cả các lệnh gọi đến hàm sẽ trả về các giá trị cụ thể theo thứ tự cho đến khi đến cuối danh sách giá trị trả về, tại đó nó sẽ trả về không xác định cho tất cả các cuộc gọi tiếp theo.

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

Đây là câu trả lời chính xác, vì một bài kiểm tra phải luôn biết chính xác cách thức một điệp viên sẽ được gọi, và do đó chỉ nên sử dụng returnValuesđể hỗ trợ nhiều cuộc gọi
Schmuli

2
Chỉ cần làm rõ câu trả lời của akhouri: phương pháp này chỉ hoạt động khi externalApi.get.and.returnValues('abc','123')được gọi trong ithàm. Mặt khác, nếu bạn thiết lập một danh sách các giá trị, nếu không, nó sẽ không bao giờ hoạt động vì thứ tự chạy thử nghiệm là không thể dự đoán được. Trong thực tế kiểm tra không nên phụ thuộc vào thứ tự mà chúng được thực hiện.
avi.elkharrat

0

Trong trường hợp của tôi, tôi đã có một thành phần mà tôi đang thử nghiệm và trong hàm tạo của nó, có một dịch vụ cấu hình với một phương thức gọi là getAppConfigValue được gọi hai lần, mỗi lần với các đối số khác nhau:

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

Trong thông số kỹ thuật của mình, tôi đã cung cấp dịch vụ Cấu hình trong TestBed như sau:

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

Vì vậy, miễn là chữ ký cho getAppConfigValue giống như được chỉ định trong Cấu hình dịch vụ thực tế, những gì chức năng thực hiện bên trong có thể được sửa đổi.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.