次のファイルセットがあります。カルマとジャスミンを使用して単体テストを実行しようとしています。 「ng test」を実行するたびに、カルマページで次のエラーが発生します。
Error: StaticInjectorError(DynamicTestModule)[ConfigService -> HttpClient]:
StaticInjectorError(Platform: core)[ConfigService -> HttpClient]:
NullInjectorError: No provider for HttpClient!
at _NullInjector.webpackJsonp../node_modules/@angular/core/esm5/core.js._NullInjector.get (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:1002:1)
at resolveToken (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:1300:1)
at tryResolveToken (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:1242:1)
at StaticInjector.webpackJsonp../node_modules/@angular/core/esm5/core.js.StaticInjector.get (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:1110:1)
at resolveToken (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:1300:1)
at tryResolveToken (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:1242:1)
at StaticInjector.webpackJsonp../node_modules/@angular/core/esm5/core.js.StaticInjector.get (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:1110:1)
at resolveNgModuleDep (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:10854:1)
at _createClass (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:10891:1)
at _createProviderInstance$1 (http://localhost:9876/_karma_webpack_/webpack:/node_modules/@angular/core/esm5/core.js:10865:1)
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"];
}
};
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:"[email protected]", password:"aaa", IsValid:false},
{username:"user1cerebra.com", password:"aa", IsValid:false},
{username:"user1cerebra.com", password:"qwqwqwqw", IsValid:false},
{username:"[email protected]", password:"qwqwqwqw", IsValid:true},
{username:"[email protected]", 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']);
});
}
});
上記のファイルのセットがあります。カルマとジャスミンを使用して単体テストを実行しようとしています。 「ng test」を実行するたびに、カルマページでエラーが発生します。この問題の解決を手伝ってください。前もって感謝します:)。
httpClientTestingModuleをインポートする
import { HttpClientTestingModule, HttpTestingController} from '@angular/common/http/testing';
TestBed.configureTestingModule({
imports: [
RouterTestingModule.withRoutes([]),
FormsModule,
HttpClientTestingModule
...
そして、インジェクトを使用してhttpClient呼び出しをテストします
it(
'your test',
inject(
[HttpTestingController, MembershipService],
(httpMock: HttpTestingController, configshipService: ConfigService ) =>
{
...
}))