199 votes

Y a-t-il un moyen de modifier les espions de Jasmine en fonction des arguments ?

J'ai une fonction que j'aimerais tester et qui appelle deux fois une méthode API externe, en utilisant des paramètres différents. J'aimerais simuler cette API externe avec un espion Jasmine et renvoyer différentes choses en fonction des paramètres. Existe-t-il un moyen de faire cela dans Jasmine ? Le mieux que j'ai pu trouver est un hack utilisant 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;
      }
    });
  });
});

307voto

Andreas Köberle Points 16453

Dans les versions 3.0 et supérieures de Jasmine, vous pouvez utiliser 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);
  });
});

Pour les versions de Jasmine antérieures à 3.0 callFake est la bonne méthode, mais vous pouvez la simplifier en utilisant un objet pour contenir les valeurs de retour.

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

Selon la version de Jasmine, la syntaxe est légèrement différente :

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

Ressources :

13voto

vas Points 24

Vous pouvez également utiliser $provide pour créer un espion. Et simuler en utilisant and.returnValues au lieu de and.returnValue pour transmettre des données paramétrées.

Comme dans les documents de Jasmine : En enchaînant l'espion avec and.returnValues Dans le cas d'un appel à la fonction, tous les appels à la fonction renverront des valeurs spécifiques dans l'ordre, jusqu'à ce que la fonction atteigne la fin de la liste des valeurs de retour.

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

0voto

Guillermo Points 1

Dans mon cas, j'avais un composant que je testais et, dans son constructeur, il y a un service de configuration avec une méthode appelée getAppConfigValue qui est appelé deux fois, chaque fois avec des arguments différents :

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

Dans ma spécification, j'ai fourni le ConfigService dans le TestBed comme suit :

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

Donc, tant que la signature pour getAppConfigValue est la même que celle spécifiée dans le ConfigService réel, ce que la fonction fait en interne peut être modifié.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X