因果报应+;茉莉花&x2B;Angular 4-NullInjectorError:没有HttpClient的提供程序

因果报应+;茉莉花&x2B;Angular 4-NullInjectorError:没有HttpClient的提供程序,angular,unit-testing,testing,jasmine,karma-runner,Angular,Unit Testing,Testing,Jasmine,Karma Runner,我有以下一组文件。 我正在尝试使用karma和jasmine运行单元测试。 每当我运行“ng测试”时,我都会在karma页面中发现以下错误。 app.module.ts import { ConfigService } from './config-service.service'; import { BrowserModule } from '@angular/platform-browser'; import { NgModule, APP_INITIALIZER } from '@ang

我有以下一组文件。 我正在尝试使用karma和jasmine运行单元测试。 每当我运行“ng测试”时,我都会在karma页面中发现以下错误。

app.module.ts

import { ConfigService } from './config-service.service';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { FormGroup, FormsModule, FormControl, Validators, ReactiveFormsModule, FormBuilder } from '@angular/forms';
import { RouterModule, Routes } from '@angular/router';
import { HttpModule } from '@angular/http';
import { StorageServiceModule} from 'angular-webstorage-service';
import { LoadingBarHttpModule } from '@ngx-loading-bar/http';
import { HttpClientModule } from "@angular/common/http";

import { AppComponent } from './app.component';
import { FooterComponent } from './footer/footer.component';
import { ForgotPasswordComponent } from './forgot-password/forgot-password.component';
import { ResetPasswordComponent } from './reset-password/reset-password.component';
import { LoginPageComponent } from './login-page/login-page.component';
import { ResetPasswordGuardGuard } from './reset-password-guard.guard';


export function getMetaData(cs: ConfigService) {
  return () => cs.getMetaData();
}
const appRoutes:Routes = [
  {   path: '',
      component: LoginPageComponent
  },{
      path: 'resetPassword',
      canActivate: [ResetPasswordGuardGuard],
      component: ResetPasswordComponent
  },{
      path: 'login',
      component: LoginPageComponent
  },{
    path: 'forgotPassword',
    component: ForgotPasswordComponent
  }
]
@NgModule({
  declarations: [
    AppComponent,
    FooterComponent,
    ForgotPasswordComponent,
    ResetPasswordComponent,
    LoginPageComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    RouterModule.forRoot(appRoutes, {useHash: true}),
    HttpModule,
    StorageServiceModule,
    ReactiveFormsModule,
    LoadingBarHttpModule,
    HttpClientModule,
  ],
  providers: [
    ConfigService,
    ResetPasswordGuardGuard,
    { 
      provide: APP_INITIALIZER, 
      useFactory: getMetaData,
      deps: [ConfigService], 
      multi: true 
    },
  ],
  bootstrap: [AppComponent],
  exports: [RouterModule]
})
export class AppModule { }
config.service.ts

import { ForgotPasswordComponent } from './forgot-password/forgot-password.component';
import { LoginPageComponent } from './login-page/login-page.component';
import { Injectable, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class ConfigService {
  private urls:object = {
    loginPage       : "/api/loginValidate",
    forgotPassword  : "/api/forgotPassword",
    resetPassword   : "/api/resetPassword",
    tokenLength     : 30,
    token           : "unique"
    };
  private metaData:object;
  private footer = {    client : {},    provider:{}  };
  private metaDataURL = "/api/getMetaData";
  constructor(private httpClient: HttpClient) {  }
  getMetaData(): Promise<any> {
    const promise = this.httpClient.get(this.metaDataURL)
      .toPromise()
      .then(data => {
        this.metaData = data;
        this.footer.client = this.metaData['companyDetails'][this.metaData['defaultSettings']]['client'];
        this.footer.provider = this.metaData['companyDetails'][this.metaData['defaultSettings']]['provider'];
        return data;
      });
    return promise;
  }
  getLogoUrl(){
    return this.metaData['companyDetails'][this.metaData['defaultSettings']]['imgURL'];
  }
  getFooter(){
    return this.footer;
  }
  //------------------- RESET PASS PAGE -------------------
  getLengthOfToken(){
    return this.urls["tokenLength"];
  }
  getResetPasswordToken(){
    return this.urls["token"];
  }
  getResetPassUrl(){
    return this.urls["resetPassword"];

  }
  //------------------- FORGOT PASS PAGE -------------------
  getForgotPassUrl(){
    return this.urls["forgotPassword"];
  }
  //------------------- LOGIN PASS PAGE -------------------
  getloginUrl(){
    return this.urls["loginPage"];
  }
};
从“.”导入{ForgotPasswordComponent}/ForgotedPassword/ForgotedPassword.component';
从“./login page/login page.component”导入{LoginPageComponent};
从“@angular/core”导入{Injectable,OnInit};
从'@angular/common/http'导入{HttpClient};
@可注射()
导出类配置服务{
专用URL:对象={
登录页面:“/api/loginValidate”,
forgotPassword:“/api/forgotPassword”,
重置密码:“/api/resetPassword”,
长度:30,
标记:“唯一”
};
私有元数据:对象;
私有页脚={client:{},provider:{};
私有元数据URL=“/api/getMetaData”;
构造函数(私有httpClient:httpClient){}
getMetaData():承诺{
const promise=this.httpClient.get(this.metaDataURL)
.toPromise()
。然后(数据=>{
this.metaData=数据;
this.footer.client=this.metaData['companyDetails'][this.metaData['defaultSettings']]['client'];
this.footer.provider=this.metaData['companyDetails'][this.metaData['defaultSettings']]['provider'];
返回数据;
});
回报承诺;
}
getLogoUrl(){
返回this.metaData['companyDetails'][this.metaData['defaultSettings']]['imgURL'];
}
getFooter(){
返回此.footer;
}
//-------------------重置通行证页面-------------------
getLengthOfToken(){
返回此.url[“tokenLength”];
}
getResetPasswordToken(){
返回此.url[“token”];
}
getResetPassUrl(){
返回此.url[“重置密码”];
}
//-------------------忘记传递页-------------------
getForgotPassUrl(){
返回此.url[“forgotPassword”];
}
//-------------------登录通行证页面-------------------
getloginUrl(){
返回此.url[“loginPage”];
}
};
login-page.component.ts

    import { ConfigService } from './../config-service.service';
    import { Component, OnInit, AfterViewInit, ElementRef } from '@angular/core';
    import { Router } from '@angular/router';
    import { FormGroup,FormsModule, FormControl, Validators ,ReactiveFormsModule, FormBuilder } from '@angular/forms';
    import { Http, Response} from '@angular/http';
    import 'rxjs/add/operator/map';
    import {LOCAL_STORAGE, SESSION_STORAGE} from 'angular-webstorage-service';
    import { LoadingBarHttpModule } from '@ngx-loading-bar/http';

    @Component({
      selector: 'app-login-page',
      templateUrl: './login-page.component.html',
      styleUrls: ['./login-page.component.scss']
    })
    export class LoginPageComponent  {
      usernameRegex = new RegExp("[a-zA-Z0-9.-_]{1,}@[a-zA-Z.-]{2,}[.]{1}[a-zA-Z]{2,}");
      logoUrl:string;
      showInvalidCredError = false;
      showServerError = false;
      form: FormGroup;
      constructor(private fb:FormBuilder, private router:Router,private http: Http,private service: ConfigService) {
      console.log("login.comp");    

        this.form = fb.group({
          "username": ['', [Validators.required, Validators.minLength(2), Validators.pattern(this.usernameRegex)]],
          "password": ['', [Validators.required, Validators.minLength(6)]],
          "rememberMe": ['']
        });
        // this.logoUrl="assets/images/cerebra_logo.png";
        // service.getMetaData();
        this.logoUrl=this.service.getLogoUrl();
        if(localStorage.getItem("appCredsUsername") && localStorage.getItem("appCredsPassword")){
          this.form.setValue(
            {  username   : localStorage.getItem("appCredsUsername"),
               password   : localStorage.getItem("appCredsPassword"),
               rememberMe : true
            }
          );
        }   
       }
      b64EncodeUnicode(str) {
            return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
                function toSolidBytes(match, p1) {
            var temp:string = String.fromCharCode(+('0x' + p1));
                    return temp;
            }));
        }
      getData(param){                                           // used for making http calls
        return this.http.post(this.service.getloginUrl(),param).map((res: Response)=> res.json());  
      }
      get username(){                                                  // to get username for form validation
        return this.form.get("username");
      }
      get password(){                                                  // to get password for form validation
        return this.form.get("password");
      }
      forgotPassword(){                                                // routing to forget password page
        this.router.navigate(['forgotPassword']);
      }
      hideError(){
        this.showInvalidCredError = false;
        this.showServerError = false;
      }
      checkAuth(){
        if(this.form.controls.username.status=='VALID' && this.form.controls.password.status == 'VALID'){
          if(this.form.get("rememberMe").value == true){
            localStorage.setItem("appCredsUsername",this.username.value);
            localStorage.setItem("appCredsPassword",this.password.value);
            localStorage.setItem("appCredsRememberMe",'true');
          }
          else{
            localStorage.setItem("appCredsUsername","");
            localStorage.setItem("appCredsPassword","");
            localStorage.setItem("appCredsRememberMe",'false');

          }
          var param = {
            "username"  : this.username.value.toLowerCase(),
            "password"  : this.b64EncodeUnicode(this.password.value)
            };
          this.getData(param).subscribe(data => {
            if(data["status"]=="ERROR"){                                    // server down or something
              this.showServerError = true;
            }else if(data["status"] == "SUCCESS"){                          //success, got app name, will redirect now.
              sessionStorage.setItem("appToken",data["token"]);             //setting recived JWT token in session.
              location.href = data["pageUrl"];                              //Redirection Actual URL sent by API
            }else if(data["status"]=="FAILED"){                             //invalid username password entered
              this.showInvalidCredError = true;
            }
          });
        }
      }
    }

login-page.component.spec.ts

import { async, inject, ComponentFixture, TestBed } from '@angular/core/testing';
import {ReactiveFormsModule, FormsModule} from "@angular/forms";
import { Injectable } from '@angular/core';
import { LoginPageComponent } from './login-page.component';
import { RouterTestingModule } from '@angular/router/testing';
import { MockBackend, MockConnection } from '@angular/http/testing';
import { ConfigService } from './../config-service.service';
import {
  Http, ResponseOptions,
  Response, BaseRequestOptions, ConnectionBackend, RequestOptions
} from '@angular/http';
import { HttpClientModule } from '@angular/common/http';

var loginArray : object[] = [
  {username:"", password:"", IsValid:false},
  {username:"user1", password:"qwqwqwqw", IsValid:false},
  {username:"user1@cerebra", password:"", IsValid:false},
  {username:"user1@cerebra.com", password:"aaa", IsValid:false},
  {username:"user1cerebra.com", password:"aa", IsValid:false},
  {username:"user1cerebra.com", password:"qwqwqwqw", IsValid:false},
  {username:"user1@cerebra.com", password:"qwqwqwqw", IsValid:true},
  {username:"admin@cerebra.com", password:"qwqwqwqw", IsValid:true},  
];

@Injectable()
class validateMock {
  constructor(private _http: Http) {}
  getSomething(url) {
    return this._http.get(url).map(res => res.text());
  }
}

describe('LoginPageComponent', async() => {
  let component: LoginPageComponent;
  let fixture: ComponentFixture<LoginPageComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports : [
        ReactiveFormsModule, 
        FormsModule, 
        RouterTestingModule, 
        HttpClientModule],
      declarations: [LoginPageComponent],
      providers: [
        ReactiveFormsModule, 
        // BaseRequestOptions,
        // MockBackend,
        // BaseRequestOptions,
        ConfigService]
    }).compileComponents();

    fixture = TestBed.createComponent(LoginPageComponent);
    component = fixture.componentInstance;
  });
  //Mocking The HTTP Call and getting the Response
  it('should get Validation Response', async(inject([validateMock, MockBackend],
    (service: validateMock, backend: MockBackend) => {
      backend.connections.subscribe((conn: MockConnection) => {
        const options: ResponseOptions = new ResponseOptions({body:'Hola'});
        conn.mockRespond(new Response(options));
    });
})));
  //Iteration over an Array to check all possible test cases
  for(let i = 0; i < loginArray.length; i++){
    it("username:"+loginArray[i]['username']+", IsValid: "+loginArray[i]['IsValid'],() => {
      let userName = component.form.controls['username'];
      userName.setValue(loginArray[i]['username']);
      let password = component.form.controls['password'];
      password.setValue(loginArray[i]['password']);
      expect(component.form.valid).toBe(loginArray[i]['IsValid']);
    });
  }
});
从“/../config service.service”导入{ConfigService};
从“@angular/core”导入{Component,OnInit,AfterViewInit,ElementRef};
从'@angular/Router'导入{Router};
从'@angular/forms'导入{FormGroup,FormsModule,FormControl,Validators,ReactiveFormsModule,FormBuilder};
从'@angular/Http'导入{Http,Response};
导入'rxjs/add/operator/map';
从'angular webstorage service'导入{LOCAL_STORAGE,SESSION_STORAGE};
从'@ngx加载条/http'导入{LoadingBarHttpModule};
@组成部分({
选择器:“应用程序登录页”,
templateUrl:'./login page.component.html',
样式URL:['./登录页面.component.scss']
})
导出类LoginPageComponent{
usernameRegex=newregexp(“[a-zA-Z0-9.-{1,}@[a-zA-Z.-]{2,}[.]{1}[a-zA-Z]{2,}”);
logoUrl:string;
showInvalidCredError=false;
showServerError=false;
表格:表格组;
构造函数(专用fb:FormBuilder、专用路由器:路由器、专用http:http、专用服务:ConfigService){
console.log(“login.comp”);
this.form=fb.group({
“用户名”:[“”,[Validators.required,Validators.minLength(2),Validators.pattern(this.usernameRegex)],
“密码”:[“”,[Validators.required,Validators.minLength(6)],
“记住”:[“”]
});
//this.logoUrl=“assets/images/cerebra_logo.png”;
//service.getMetaData();
this.logoUrl=this.service.getLogoUrl();
if(localStorage.getItem(“appCredsUsername”)&&localStorage.getItem(“appCredsPassword”)){
this.form.setValue(
{用户名:localStorage.getItem(“AppCredUserName”),
密码:localStorage.getItem(“appCredsPassword”),
记住:是的
}
);
}   
}
B64Unicode编码(str){
返回btoa(encodeURIComponent(str)。替换(/%([0-9A-F]{2})/g,
函数到实字节(匹配,p1){
var-temp:string=string.fromCharCode(+('0x'+p1));
返回温度;
}));
}
getData(param){//用于进行http调用
返回this.http.post(this.service.getloginUrl(),param).map((res:Response)=>res.json());
}
get username(){//获取表单验证的用户名
返回此.form.get(“用户名”);
}
get password(){//获取表单验证的密码
返回此.form.get(“密码”);
}
forgotPassword(){//路由到忘记密码页
这个.router.navigate(['forgotPassword']);
}
hideError(){
this.showInvalidCredError=false;
this.showServerError=false;
}
checkAuth(){
if(this.form.controls.username.status='VALID'&&this.form.controls.password.status=='VALID'){
if(this.form.get(“rememberMe”).value==true){
localStorage.setItem(“appCredsUsername”,this.username.value);
setItem(“appCredsPassword”,this.password.value);
setItem(“appCredsRememberMe”,“true”);
}
否则{
setItem(“AppCredUserName”,即“”);
setItem(“AppCredPassword”和“”);
setItem(“appCredsRememberMe”,“false”);
}
变量参数={
“username”:this.username.value.toLowerCase(),
“密码”:this.b64EncodeUnicode(this.password.value)
};
this.getData(param).subscribe(数据=>{
如果(数据[“状态”]=“错误”){//服务器关闭或其他情况
    import { ConfigService } from './../config-service.service';
    import { Component, OnInit, AfterViewInit, ElementRef } from '@angular/core';
    import { Router } from '@angular/router';
    import { FormGroup,FormsModule, FormControl, Validators ,ReactiveFormsModule, FormBuilder } from '@angular/forms';
    import { Http, Response} from '@angular/http';
    import 'rxjs/add/operator/map';
    import {LOCAL_STORAGE, SESSION_STORAGE} from 'angular-webstorage-service';
    import { LoadingBarHttpModule } from '@ngx-loading-bar/http';

    @Component({
      selector: 'app-login-page',
      templateUrl: './login-page.component.html',
      styleUrls: ['./login-page.component.scss']
    })
    export class LoginPageComponent  {
      usernameRegex = new RegExp("[a-zA-Z0-9.-_]{1,}@[a-zA-Z.-]{2,}[.]{1}[a-zA-Z]{2,}");
      logoUrl:string;
      showInvalidCredError = false;
      showServerError = false;
      form: FormGroup;
      constructor(private fb:FormBuilder, private router:Router,private http: Http,private service: ConfigService) {
      console.log("login.comp");    

        this.form = fb.group({
          "username": ['', [Validators.required, Validators.minLength(2), Validators.pattern(this.usernameRegex)]],
          "password": ['', [Validators.required, Validators.minLength(6)]],
          "rememberMe": ['']
        });
        // this.logoUrl="assets/images/cerebra_logo.png";
        // service.getMetaData();
        this.logoUrl=this.service.getLogoUrl();
        if(localStorage.getItem("appCredsUsername") && localStorage.getItem("appCredsPassword")){
          this.form.setValue(
            {  username   : localStorage.getItem("appCredsUsername"),
               password   : localStorage.getItem("appCredsPassword"),
               rememberMe : true
            }
          );
        }   
       }
      b64EncodeUnicode(str) {
            return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g,
                function toSolidBytes(match, p1) {
            var temp:string = String.fromCharCode(+('0x' + p1));
                    return temp;
            }));
        }
      getData(param){                                           // used for making http calls
        return this.http.post(this.service.getloginUrl(),param).map((res: Response)=> res.json());  
      }
      get username(){                                                  // to get username for form validation
        return this.form.get("username");
      }
      get password(){                                                  // to get password for form validation
        return this.form.get("password");
      }
      forgotPassword(){                                                // routing to forget password page
        this.router.navigate(['forgotPassword']);
      }
      hideError(){
        this.showInvalidCredError = false;
        this.showServerError = false;
      }
      checkAuth(){
        if(this.form.controls.username.status=='VALID' && this.form.controls.password.status == 'VALID'){
          if(this.form.get("rememberMe").value == true){
            localStorage.setItem("appCredsUsername",this.username.value);
            localStorage.setItem("appCredsPassword",this.password.value);
            localStorage.setItem("appCredsRememberMe",'true');
          }
          else{
            localStorage.setItem("appCredsUsername","");
            localStorage.setItem("appCredsPassword","");
            localStorage.setItem("appCredsRememberMe",'false');

          }
          var param = {
            "username"  : this.username.value.toLowerCase(),
            "password"  : this.b64EncodeUnicode(this.password.value)
            };
          this.getData(param).subscribe(data => {
            if(data["status"]=="ERROR"){                                    // server down or something
              this.showServerError = true;
            }else if(data["status"] == "SUCCESS"){                          //success, got app name, will redirect now.
              sessionStorage.setItem("appToken",data["token"]);             //setting recived JWT token in session.
              location.href = data["pageUrl"];                              //Redirection Actual URL sent by API
            }else if(data["status"]=="FAILED"){                             //invalid username password entered
              this.showInvalidCredError = true;
            }
          });
        }
      }
    }

login-page.component.spec.ts

import { async, inject, ComponentFixture, TestBed } from '@angular/core/testing';
import {ReactiveFormsModule, FormsModule} from "@angular/forms";
import { Injectable } from '@angular/core';
import { LoginPageComponent } from './login-page.component';
import { RouterTestingModule } from '@angular/router/testing';
import { MockBackend, MockConnection } from '@angular/http/testing';
import { ConfigService } from './../config-service.service';
import {
  Http, ResponseOptions,
  Response, BaseRequestOptions, ConnectionBackend, RequestOptions
} from '@angular/http';
import { HttpClientModule } from '@angular/common/http';

var loginArray : object[] = [
  {username:"", password:"", IsValid:false},
  {username:"user1", password:"qwqwqwqw", IsValid:false},
  {username:"user1@cerebra", password:"", IsValid:false},
  {username:"user1@cerebra.com", password:"aaa", IsValid:false},
  {username:"user1cerebra.com", password:"aa", IsValid:false},
  {username:"user1cerebra.com", password:"qwqwqwqw", IsValid:false},
  {username:"user1@cerebra.com", password:"qwqwqwqw", IsValid:true},
  {username:"admin@cerebra.com", password:"qwqwqwqw", IsValid:true},  
];

@Injectable()
class validateMock {
  constructor(private _http: Http) {}
  getSomething(url) {
    return this._http.get(url).map(res => res.text());
  }
}

describe('LoginPageComponent', async() => {
  let component: LoginPageComponent;
  let fixture: ComponentFixture<LoginPageComponent>;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports : [
        ReactiveFormsModule, 
        FormsModule, 
        RouterTestingModule, 
        HttpClientModule],
      declarations: [LoginPageComponent],
      providers: [
        ReactiveFormsModule, 
        // BaseRequestOptions,
        // MockBackend,
        // BaseRequestOptions,
        ConfigService]
    }).compileComponents();

    fixture = TestBed.createComponent(LoginPageComponent);
    component = fixture.componentInstance;
  });
  //Mocking The HTTP Call and getting the Response
  it('should get Validation Response', async(inject([validateMock, MockBackend],
    (service: validateMock, backend: MockBackend) => {
      backend.connections.subscribe((conn: MockConnection) => {
        const options: ResponseOptions = new ResponseOptions({body:'Hola'});
        conn.mockRespond(new Response(options));
    });
})));
  //Iteration over an Array to check all possible test cases
  for(let i = 0; i < loginArray.length; i++){
    it("username:"+loginArray[i]['username']+", IsValid: "+loginArray[i]['IsValid'],() => {
      let userName = component.form.controls['username'];
      userName.setValue(loginArray[i]['username']);
      let password = component.form.controls['password'];
      password.setValue(loginArray[i]['password']);
      expect(component.form.valid).toBe(loginArray[i]['IsValid']);
    });
  }
});
  import { HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';

  TestBed.configureTestingModule({
  imports: [
    RouterTestingModule.withRoutes([]),
    FormsModule,
    HttpClientTestingModule
    ...
it('your test', inject([HttpTestingController, MembershipService],
   (httpMock: HttpTestingController, configshipService: ConfigService ) => 
 { 
   ...
 })
)