web-dev-qa-db-fra.com

Test Angular5/ng ERREUR: TypeError: this.handler.handle n'est pas une fonction

C'est ma configuration angulaire:

Angular CLI: 1.7.2
Node: 6.10.0
OS: win32 x64
Angular: 5.2.5
... animations, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

@angular/cli: 1.7.2
@angular-devkit/build-optimizer: 0.3.2
@angular-devkit/core: 0.3.2
@angular-devkit/schematics: 0.3.2
@ngtools/json-schema: 1.2.0
@ngtools/webpack: 1.10.1
@schematics/angular: 0.3.2
@schematics/package-update: 0.3.2
TypeScript: 2.6.2
webpack: 3.11.0

Mon fichier package.json: 

{
  "name": "xxxx",
  "version": "0.0.0",
  "license": "MIT",
  "scripts": {
    "ng": "ng",
    "start": "ng serve --proxy-config proxy.conf.json",
    "build": "ng build --prod",
    "test": "ng test",
    "lint": "ng lint",
    "e2e": "ng e2e",
    "ng2ninja": "ng2ninja"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "5.2.5",
    "@angular/common": "5.2.5",
    "@angular/compiler": "5.2.5",
    "@angular/core": "5.2.5",
    "@angular/forms": "5.2.5",
    "@angular/platform-browser": "5.2.5",
    "@angular/platform-browser-dynamic": "5.2.5",
    "@angular/router": "5.2.5",
    "@ng-bootstrap/ng-bootstrap": "^1.0.0",
    "bootstrap": "4.0.0",
    "core-js": "2.4.1",
    "font-awesome": "4.7.0",
    "rxjs": "5.5.6",
    "tslint-sonarts": "^1.6.0",
    "yarn": "^1.5.1",
    "zone.js": "0.8.19"
  },
  "devDependencies": {
    "@angular/cli": "^1.7.1",
    "@angular/compiler-cli": "5.2.5",
    "@angular/language-service": "5.2.5",
    "@types/jasmine": "2.8.6",
    "@types/jasminewd2": "2.0.3",
    "@types/node": "8.5.2",
    "@ng-bootstrap/ng-bootstrap": "1.0.0",
    "angular-ide": "^0.9.39",
    "codelyzer": "4.1.0",
    "jasmine-core": "2.8.0",
    "jasmine-spec-reporter": "4.2.1",
    "karma": "2.0.0",
    "karma-chrome-launcher": "2.2.0",
    "karma-coverage-istanbul-reporter": "1.3.3",
    "karma-firefox-launcher": "1.1.0",
    "karma-jasmine": "1.1.1",
    "karma-jasmine-html-reporter": "0.2.2",
    "karma-json-reporter": "1.2.1",
    "ng2ninja": "1.0.17",
    "protractor": "5.2.2",
    "ts-node": "4.1.0",
    "tslint": "5.9.1",
    "TypeScript": "2.6.2"
  }
}

J'obtiens ce message d'erreur lorsque j'exécute la commande 'ng test' :

 TypeError: this.handler.handle is not a function
            at MergeMapSubscriber.__WEBPACK_IMPORTED_MODULE_2_rxjs_operator_concatMap__.a.call [as project] node_modules/@angular/common/esm2015/http.js:1174:28)
            at MergeMapSubscriber._tryNext node_modules/rxjs/_esm2015/operators/mergeMap.js:109:1)
            at MergeMapSubscriber._next node_modules/rxjs/_esm2015/operators/mergeMap.js:99:1)
            at MergeMapSubscriber.next node_modules/rxjs/_esm2015/Subscriber.js:83:1)
            at ScalarObservable._subscribe node_modules/rxjs/_esm2015/observable/ScalarObservable.js:42:1)
            at ScalarObservable._trySubscribe node_modules/rxjs/_esm2015/Observable.js:171:1)
            at ScalarObservable.subscribe node_modules/rxjs/_esm2015/Observable.js:159:1)
            at MergeMapOperator.call node_modules/rxjs/_esm2015/operators/mergeMap.js:78:1)
            at Observable.subscribe node_modules/rxjs/_esm2015/Observable.js:156:1)

Ceci est mon test:

import {TestBed, inject} from '@angular/core/testing';
import {HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
import {UserService} from './user.service';
import {environment} from '../environments/environment';
import {JwtInterceptorService} from './jwt-interceptor.service';
import {User} from './services/model/user';
import {HttpClient, HttpHandler} from '@angular/common/http';
...
     it('should authenticate a user', () => {
        // spy on the store method
        spyOn(userService, 'storeLoggedInUser');

        const credentials = {login: 'toto', password: 'titi'};
        let actualUser;
        userService.login(credentials).subscribe(fetchedUser => actualUser = fetchedUser);
    ...
      });

Après analyse et débogage, le problème provient de l’appel de la méthode "login" du service utilisateur.

Après avoir parcouru de nombreux articles (et solutions), je ne comprends pas la véritable origine de mon message d'erreur.

Ceci est mon service utilisateur:

 login(credentials): Observable<User> {
    var headers = new HttpHeaders();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');

    var paramCredentials = "grant_type=password"
      + "&credentials=true"
      + "&scope=read write"
      + "&accept=application/json"
      + "&username=" + credentials.username
      + "&password=" + credentials.password;

    return this.http.post<User>(`${environment.oAuthUrl}/oauth/token`, paramCredentials, {headers: headers}).pipe(
      tap(user => this.storeLoggedInUser(user))
    );
  }

 storeLoggedInUser(user) {
    window.localStorage.setItem('jwtToken', JSON.stringify(user));
    this.jwtInterceptorService.setJwtToken(user.token);
  }

Des idées ?

Merci d'avance

5
F. MAUPIN

Veuillez ajouter un gestionnaire d'erreurs dans votre composant.ts où vous appelez cette méthode Login (informations d'identification).

user_login() {
this.userService.login(credentials).subscribe((res) => {
console.log(res);
}, (error) => {
console.log(error);
});
7
Shubham Jain

J'ai rencontré ce problème en essayant de convertir mes tests pour utiliser HttpTestingController. Je crois que la réponse acceptée supprime simplement le problème et l’imprime sur la console. Il y a beaucoup de choses que je ne comprends toujours pas pour ma solution ci-dessous, mais j'espère que cela pourra aider quelqu'un.

Le problème dans ma candidature était que je fournissais HttpHandler dans ma liste providers. Cela causait _this.handler d'être une HttpHandler sur la ligne incriminée dans http.js, dans la trace de la pile.

var /** @type {?} */ events$ = concatMap.call(of(req), function (req) { return _this.handler.handle(req); });

J'ai supprimé HttpHandler des fournisseurs dans mon TestBed.configureTestModule et _this.handler était alors une HttpInterceptorHandler dotée de la fonction handle appropriée.

1
Bill

Probablement que vous n'utilisez pas HttpHandler et Angular ne peuvent pas trouver cela.

Essayez de supprimer HttpHandler de "importer" et "fournisseurs" dans votre app.module.ts:

import {HttpClient} from '@angular/common/http';
...
providers: [HttpClient],
0
SergeyShmakov