web-dev-qa-db-fra.com

Erreur: <spyOn>: fromEvent n'est pas déclaré accessible en écriture ou n'a pas de setter

L'ancien code utilise rxjs v5.5.12, nous avons copié le même code dans notre nouveau projet qui utilise rxjs v6.4.0. Nous obtenons cette erreur lorsque nous avons essayé d'exécuter le scénario de test.

Ancien code:

import * as ObservableEvents from 'rxjs/Observable/fromEvent';
spyOn(ObservableEvents, 'fromEvent').and.returnValue(new Subject<any>().asObservable());

Nouveau code:

import * as rxjs from 'rxjs';
spyOn(rxjs, 'fromEvent').and.returnValue(new Subject<any>().asObservable());

Dans les deux cas, nous obtenons cette erreur:

Erreur: fromEvent n'est pas déclaré accessible en écriture ou n'a pas de setter

Nous n'avons pas pu trouver de ressource valide pour résoudre ce problème.

Mise à jour # 1

Nous avons essayé d'utiliser

import * as rxjs from 'rxjs';
spyOn(jasmine.createSpyObj(rxjs), 'fromEvent').and.returnValue(new Subject<any>().asObservable());

mais cette fois, nous avons

createSpyObj nécessite un tableau ou un objet de noms de méthode non vide pour créer des espions à lancer

Mise à jour # 2:

Nous avons utilisé le code de @ Omair-Nabiel, obtenant maintenant une nouvelle erreur

      TypeError: Object(...) is not a function
          at XxxPopoverDirective.fromEvent [as createPopover] (http://xxx:xxxx/src/app/shared/xxx/xxx.directive.ts?:113:37)
          at XxxPopoverDirective.createPopover [as mouseClick] (http://xxx:xxxx/src/app/shared/xxx/xxx.directive.ts?:70:14)
          at runTest (http://xxx:xxxx/src/app/shared/xxx/xxx.directive.spec.ts?:181:19)

xxx.directive.ts

line 113-> this.componentRef && this.componentRef.destroy();
this.componentRef = null;

line 70-> constructor(
...
private resolver: ComponentFactoryResolver,
...
  ) { }

Mise à jour #

Salut Omair Nabiel, Veuillez trouver le code ci-dessous que nous utilisons, faites-moi savoir la solution,

file = "popover.directive.ts" Code:

import { fromEvent } from 'rxjs/Observable/fromEvent';

this.clickOutSub = fromEvent(this.documentRef.getDocument(), 'click').subscribe(this.clickOut.bind(this));

file="popover.directive.spec.ts"
Code:
import * as ObservableEvents from 'rxjs/Observable/fromEvent';

function runTest() {

spyOn(ObservableEvents, 'fromEvent').and.returnValue(new Subject<any>().asObservable());

 }

it('...', () => {
expect(ObservableEvents.fromEvent).toHaveBeenCalled();
});
11
Raju

Vous ne pouvez pas espionner une importation de module, car elle est en lecture seule. Voici le même problème rxjs et problème Jasmine dans GitHub.

Mais, voulez-vous vraiment espionner la fonction fromEvent? Si votre but est de vérifier si votre classe/fonction appelle fromEvent ou non, vous ne devriez pas le faire. Les tests doivent tester l'API mais pas l'implémentation. Il est difficile de maintenir de tels tests, qui testent la mise en œuvre. Vous devez tester les boîtes noires et ne pas penser à la façon dont elles sont mises en œuvre.

Si vous allez utiliser fromEvent juste à l'intérieur du test, cela ne doit pas être un problème pour tester son comportement. Si c'est important pour vous de toute façon, pour tester comment vos événements sont transformés en observables, vous pouvez créer un wrapper 'fromEvent' et vous en moquer, comme:

class EventTransformer {
  transform<T>(target: FromEventTarget<T>, eventName: string): Observable<T> {
    return fromEvent(target, eventName);
  }
}

class MyClass {
  constructor(private eventTransformer: EventTransformer) {}
  doSomething() { /* transform some event */ }
}

it('test', () => {
  const eventTransformer = jasmine.createSpyObj<EventTransformer>(EventTransformer.name, [
    'transform',
  ]);
  eventTransformer.transform.and.returnValue(of({}));

  const myClass = new MyClass(eventTransformer)
  myClass.doSomething();
});

ne autre solution , consiste à utiliser les modules 'commonjs', en mettant à jour votre test tsconfig.

"compilerOptions": {
    ....
    // force commonjs module output, since it let mock exported members on modules to anywhere in the application (even in the same file)
    "module": "commonjs",
},
2
Valeriy Katkov

Vous devez espionner une propriété de rxjs. L'utilisation de spyOnProperty résoudra l'erreur. Essaye ça

 import * as rxjs from 'rxjs'
 import { of, fromEvent } from 'rxjs';  

spyOnProperty(rxjs, 'fromEvent').and.returnValue(of({}))

vous pouvez également ajouter à getter/setters en utilisant ceci comme

spyOnProperty(rxjs, 'fromEvent', 'get').and.returnValue(false)

J'espère que cela t'aides

1
Omair Nabiel

Complétant la réponse d'Omair. Dans mon cas, j'ai besoin d'une fonction sur l'instruction returnValue.

const fromEventSpy = spyOnProperty(rxjs, 'fromEvent').and.returnValue(() => rxjs.of({}));

À votre santé!

0
Alejandro Barone