对调用服务的组件进行Angular 5单元测试

时间:2017-12-28 16:04:53

标签: angularjs unit-testing angular5

我有一个Angular 5项目,我正在为我的登录组件添加单元测试。

测试在我的“提交”按钮上,该按钮将调用REST API进行身份验证,如果成功,则返回JWT

这是我的LoginComponent.submit功能:

submit() {
    this.loggingService.log('LoginComponent | submit | ...');

    this.loginService.login(this.loginFormGroup.get('username').value, this.loginFormGroup.get('password').value)
        .subscribe((jwtString: string) => {
            window.alert('login successful, token: ' + jwtString);

            // the response should be the JWT, so let's set it
            this.authenticationService.setToken(jwtString);
        }, (error: any) => { // should this be changed to the Error type on return???
            const errorString: string = error && error.message ? error.message : error;

            this.loggingService.error('login failed ' + errorString);
            this.loginFormGroup.setErrors({ 'post': errorString });
        });
}

这是我的LoginService.login功能:

login(username: string, password: string): Observable<any> {
    this.loggingService.log('LoginService | login | loginUrl: ' + this.loginUrl + '; username: ' + username + '; password: xxxxx');

    return this.http.post(this.loginUrl, { username: username, password: password });
}

非常简单,现在这是LoginComponent的单元测试:

it('submit logs the user in successfully', () => {
    // spyOn(loginService, 'login').and.returnValue('asdfasdfasdf').and.callThrough();

    component.loginFormGroup.setValue({ username: 'roberto', password: 'password' });
    component.submit();

    expect(authenticationService.getToken()).toEqual('asdfasdfasdf');
});

执行测试时,我收到此错误:

  

'错误:登录失败_this.handler.handle不是函数'

现在,看到这一点,它让我觉得它与middleware有关。只有我拥有的中间件是HttpInterceptor,这里是代码:

intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        this.loggingService.log('CustomHttpInterceptor | intercept | intercepting http(s) transaction: ' + request.urlWithParams);

        const customRequest = this.authenticationService.isAuthenticated()
            ? request.clone({
                    headers: request.headers
                        .set('Authorization', 'Bearer ' + this.authenticationService.getToken())
                        .set('Content-type', 'application/json')
                })
            : request.clone({
                    headers: request.headers
                        .set('Content-type', 'application/json')
                });

        return next.handle(customRequest)
            .do((event: HttpEvent<any>) => {
                // need this if check here because the options calls are NOT an HttpResponse, and we don't want to do anything with them
                if (event instanceof HttpResponse) {
                    // log a successful response from the API call
                    this.loggingService.logApiCall('CustomHttpInterceptor | intercept | ' + JSON.stringify(event));
                }
            })
            .catch((error: any) => {
                // log the failed response
                this.loggingService.error('CustomHttpInterceptor | intercept | ' + JSON.stringify(error));

                if (error instanceof HttpErrorResponse && error.status === 401) {

                    // if we ever want to save our failed (401) requests, and retry after attempting to refresh the JWT,
                    // add a function to the auth service to add this HttpEvent, then after the JWT refresh, we can re-execute
                    // the http call.

                    this.router.navigate(['login']);
                }

                return Observable.throw('asdf error');
            });
    }

为了摆脱上面的错误,我必须将这一行添加到我的单元测试的开头(部分内容已在上面注释掉):

spyOn(loginService, 'login').and.returnValue('asdfasdfasdf'); // .and.callThrough()

正如您所看到的,如果我将间谍设置为明确返回我的字符串,那么处理程序错误就会消失,但现在我收到此错误:

  

TypeError:this.loginService.login(...)。subscribe不是函数

这里有什么想法吗?

编辑:回复以下评论......

beforeEach(() => {
    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;

    loginService = TestBed.get(LoginService);
    authenticationService = TestBed.get(AuthenticationService);

    fixture.detectChanges();
});

1 个答案:

答案 0 :(得分:2)

spyOn(loginService, 'login').and.returnValue(Observable.of('asdfasdfasdf'))应该有一个Observable作为返回值。例如:

display:inline-block