Bonsoir à tous,
Après plus de 4 jours de tentatives diverses, je me décide enfin à demander de l'aide.
J'ai une application Angular dont le seul but est de générer des WebElements (via @angular/elements) donc je n'ai plus d'index.html, pas de app.component, etc.
Ces éléments sont utilisés dans une application .NET Mvc qui possède deux types de choses que j'essaie de "mocker" dans mes tests unitaire:
1 - Des librairies externes
Par exemple JQuery, lodash, etc.
Je n'ajoute pas ces librairies à mon application Angular car les fichiers sources sont déjà fournit par la vue MVC qui appelle mes composants Angular, ça ferait double emploi.
2 - Framework client "foo"
Dans la vue MVC, l'application .Net MVC va créer un objet que l'on va nommé "foo". Ce n'est pas un module ES6, il est créé avec des options provenant du serveur via la session utilisateur (géré en .Net donc):
Le problème vient du fait que ces deux choses sont utilisés par mes composants Angular. Par exemple, un composant va pouvoir utiliser la fonction
Code : Sélectionner tout - Visualiser dans une fenêtre à part const foo = new Foo({ someOptionsGeneratedFromServerSide});
La solution pour faire coïncider les deux a été de référencer le fichier de définitions de l'objet foo comme suivant:
Code : Sélectionner tout - Visualiser dans une fenêtre à part foo.displayAlert('avec un message');
Je sais que c'est peu orthodoxe comme méthode mais le principe ne me parait pas fou: créer des composants réutilisable (WebElements) via Angular et s'en servir autre part. Vu que c'est dans une approche purement corporate, ces éléments utilisent les ressources interne de l'application principale (.NET Mvc): objet foo, JQuery, lodash, fichiers de styles globaux, etc.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 // tslint:disable-next-line: max-line-length no-reference /// <reference path='path/to/the/definition.d.ts' />
L'application Angular marche très bien jusqu'à ce que j'essaie de faire mes tests unitaire.
Pour information: l'application ne peut marcher toute seule: ng serve est devenu inutile dans mon cas: c'est la vue MVC qui importe tout ce qu'il faut.
Voici un exemple de test unitaire:
Pour cette partie de composant:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 it('should render title', () => { const fixture = TestBed.createComponent(AppComponent); fixture.detectChanges(); const compiled = fixture.nativeElement; expect(compiled.querySelector('.content span').textContent).toContain('ng-jest app is running!'); });
Cela ne marche pas avec le message d'erreur suivant:
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3 ngOnInit() { foo.displayAlert('With a message'); }
Ce qui n'est pas surprenant en soi: le test-runner (Karma dans ce cas) va lancer un browser qui va lancer l'application.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 AppComponent should render title ReferenceError: foo is not defined
Or, l'application ne peut marcher sans les ressources apportées par la vue MVC.
J'ai essayé de "mocker" l'objet avant le test:
Ce qui n'a pas marché, selon moi car cette variable n'est pas fournit au composant mais uniquement dans le scope du test unitaire. Peut-être la solution serait d'injecter cette variable au composant ?
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14 let foo: any; beforeEach(async(() => { TestBed.configureTestingModule({ imports: [ RouterTestingModule ], declarations: [ AppComponent ], }).compileComponents(); foo = { displayAlert: Function }; }));
J'ai essayé beaucoup de choses dans le x.spec.ts sur cet objet sans résultats probant.
J'ai créé une autre application Angular avec un index.html qui inclut manuellement toutes les ressources de la vue MVC mais cela n'a pas fonctionné non plus. Je pense que je dois également faire la même chose dans le test-runner Karma: cela marcherait je pense pour les librairies externes mais pas pour l'objet foo qui, comme dit plus haut, s'initialise avec des données serveur.
Les librairies externes telles que JQuery & lodash ne devraient pas, selon moi, être incluses dans le projet Angular: la vue MVC s'en charge et niveau taille des fichiers finaux / maintenabilité / etc. c'est mieux.
J'ai essayé de les mettre en tant que "devDependencies" dans mon gestionnaire de packet afin qu'elles ne soient pas dans les fichiers finaux: en vain.
Mon but est de de pouvoir "mocker" mon objet foo ainsi que mes librairies externes afin de pouvoir enfin avoir la possibilité de faire mes unit tests.
Dernière information: j'ai essayé avec (Jest) & sans (Karma) un "headless browser" pour les tests: même résultat.
J'aimerai vraiment arriver à faire marcher cette problématique. Je fais partie d'une boîte qui considère les tests unitaire comme étant une perte de temps et ne veut pas entendre parler de TDD. J'aimerai profiter de ce projet pour leur prouver l'utilité de ces notions (et surtout, le faire pour moi).
Votre aide me serait plus que précieuse. Je commence à réellement désespéré.
Merci d'avance!
Etienne.
Partager