web-dev-qa-db-fra.com

Comment spyOn une propriété de valeur (plutôt qu'une méthode) avec Jasmine

La méthode spyOn de Jasmine permet de modifier le comportement d'une méthode, mais existe-t-il un moyen de modifier une propriété de valeur (plutôt qu'une méthode) pour un objet? le code pourrait être comme ci-dessous:

spyOn(myObj, 'valueA').andReturn(1);
expect(myObj.valueA).toBe(1);
90
Shuping

En février 2017, ils ont fusionné un RP en ajoutant cette fonctionnalité, qu'ils ont publiée en avril 2017.

pour espionner les accesseurs que vous utilisez: const spy = spyOnProperty(myObj, 'myGetterName', 'get'); où myObj est votre instance, 'myGetterName' est le nom de celle définie dans votre classe comme get myGetterName() {} et le troisième paramètre est le tapez get ou set.

Vous pouvez utiliser les mêmes assertions que vous utilisez déjà avec les espions créés avec spyOn.

Donc vous pouvez par exemple:

const spy = spyOnProperty(myObj, 'myGetterName', 'get'); // to stub and return nothing. Just spy and stub.
const spy = spyOnProperty(myObj, 'myGetterName', 'get').and.returnValue(1); // to stub and return 1 or any value as needed.
const spy = spyOnProperty(myObj, 'myGetterName', 'get').and.callThrough(); // Call the real thing.

Voici la ligne du code source de github où cette méthode est disponible si vous êtes intéressé.

https://github.com/jasmine/jasmine/blob/7f8f2b5e7a7af70d7f6b629331eb6fe0a7cb9279/src/core/requireInterface.js#L199

En répondant à la question initiale, avec jasmine 2.6.1, vous pouvez:

const spy = spyOnProperty(myObj, 'valueA', 'get').andReturn(1);
expect(myObj.valueA).toBe(1);
expect(spy).toHaveBeenCalled();
77
Juan

Jasmine ne possède pas cette fonctionnalité, mais vous pourrez peut-être pirater quelque chose ensemble à l'aide de Object.defineProperty.

Vous pouvez refactoriser votre code pour utiliser une fonction getter, puis espionner le getter.

spyOn(myObj, 'getValueA').andReturn(1);
expect(myObj.getValueA()).toBe(1);
12
Eric

Une raison pour laquelle vous ne pouvez pas simplement le changer directement sur l'objet? Ce n'est pas comme si javascript imposait la visibilité d'une propriété sur un objet.

9
Paul Harris

Le meilleur moyen est d'utiliser spyOnProperty. Il attend 3 paramètres et vous devez passer get ou set en tant que troisième paramètre.

Exemple

const div = fixture.debugElement.query(By.css('.Ellipsis-overflow'));
// now mock properties
spyOnProperty(div.nativeElement, 'clientWidth', 'get').and.returnValue(1400);
spyOnProperty(div.nativeElement, 'scrollWidth', 'get').and.returnValue(2400);

Ici, je mets le get de clientWidth de div.nativeElement objet.

6
Aniruddha Das

Si vous utilisez ES6 (Babel) ou TypeScript, vous pouvez tronquer la propriété à l'aide des accesseurs get et set.

export class SomeClassStub {
  getValueA = jasmine.createSpy('getValueA');
  setValueA = jasmine.createSpy('setValueA');
  get valueA() { return this.getValueA(); }
  set valueA(value) { this.setValueA(value); }
}

Ensuite, dans votre test, vous pouvez vérifier que la propriété est définie avec:

stub.valueA = 'foo';

expect(stub.setValueA).toHaveBeenCalledWith('foo');
3
Martin

J'utilise une grille de kendo et je ne peux donc pas utiliser une méthode getter pour l'implémentation, mais je souhaite tester cette possibilité (se moquer de la grille) et ne pas tester la grille elle-même. J'utilisais un objet espion mais ceci ne supporte pas la propriété moqueuse alors je le fais:

    this.$scope.ticketsGrid = { 
        showColumn: jasmine.createSpy('showColumn'),
        hideColumn: jasmine.createSpy('hideColumn'),
        select: jasmine.createSpy('select'),
        dataItem: jasmine.createSpy('dataItem'),
        _data: []
    } 

C'est un peu long mais ça marche un régal

1
jolySoft

La bonne façon de faire est d’espionner les propriétés, cela vous permettra de simuler une propriété sur un objet avec une valeur spécifique.

const spy = spyOnProperty(myObj, 'valueA').and.returnValue(1);
expect(myObj.valueA).toBe(1);
expect(spy).toHaveBeenCalled();
1
alexalejandroem

Supposons qu’une méthode comme celle-ci nécessite des tests. La propriété src de la petite image doit être vérifiée.

function reportABCEvent(cat, type, val) {
                var i1 = new Image(1, 1);
                var link = getABC('creosote');
                    link += "&category=" + String(cat);
                    link += "&event_type=" + String(type);
                    link += "&event_value=" + String(val);
                    i1.src = link;
                }

Le spyOn () ci-dessous provoque l'alimentation de la "nouvelle image" avec le faux code à partir du test. Le code spyOn renvoie un objet qui n'a qu'une propriété src.

Comme la variable "hook" est visible pour être visible dans le faux code dans le SpyOn et aussi plus tard après que le "reportABCEvent" soit appelé

describe("Alphabetic.ads", function() {
    it("ABC events create an image request", function() {
    var hook={};
    spyOn(window, 'Image').andCallFake( function(x,y) {
          hook={ src: {} }
          return hook;
      }
      );
      reportABCEvent('testa', 'testb', 'testc');
      expect(hook.src).
      toEqual('[zubzub]&arg1=testa&arg2=testb&event_value=testc');
    });

Ceci est pour jasmine 1.3 mais peut fonctionner en 2.0 si "andCallFake" est modifié en nom 2.0

1
Vorsprung

Je sais que je suis un peu en retard à la fête, mais

Vous pouvez accéder directement à l'objet call, qui peut vous donner les variables pour chaque appel

expect(spy.calls.argsFor(0)[0].value).toBe(expectedValue)
0
CosmicChild