Будь-який спосіб змінити шпигунів Жасмін на основі аргументів?


146

У мене є функція, яку я хотів би перевірити, яка викликає зовнішній метод API двічі, використовуючи різні параметри. Я хотів би знущатися над цим зовнішнім 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;
      }
    });
  });
});

Відповіді:


213

У версіях Жасмін 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);
  });
});

Для версій Jasmine раніше, ніж 3.0, 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]
    });
  });
});

Залежно від версії Жасмін, синтаксис дещо відрізняється:

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

Ресурси:


11
Це зараз and.callFake- jasmine.github.io/2.2/… >
Люсі Бейн

Мені довелося повертати різні обіцянки, тому повернення виглядало дещо інакше: return q.when (params [myParam]) ;. Інакше це було місцем для вирішення моєї проблеми. Моїм рішенням мрії було б змінити дзвінки "and.returnValue".
Білл Тернер

7
вважає, що жасмін повинен мати кращий спосіб заявити про це. Як spyOn(fake, 'method').withArgs('abc').and.returnValue('Jane')і spyOn(fake, 'method').withArgs('123').and.returnValue(98765).
jrharshath

@jrharshath .withArgsне працює для мене в
жасмині

1
.withArgsнасправді недоступний - я мав на увазі, що такий метод матиме сенс при написанні тестів.
jrharshath

9

Ви також $provideможете створити шпигуна. І глузувати з використанням and.returnValuesзамість and.returnValueпередачі в параметризованих даних.

Відповідно до документів Jasmine: Об’єднавши шпигуна з 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для підтримки декількох дзвінків
Шмулі

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

В моїй специфікації я надав ConfigService в TestBed так:

{
  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, те, що функція виконує внутрішньо, можна змінювати.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.