![](/img/trans.png)
[英]Angular 4 Error: No provider for ChildrenOutletContexts in Karma-Jasmine Test
[英]Angular 2 Error: No provider for Http in Karma-Jasmine Test
即使我的應用程序完美運行且沒有錯誤,我仍然在我的業力測試中收到以下錯誤。 據說沒有Http的提供者。 我正在使用import { HttpModule } from '@angular/http';
在我的app.module.ts文件中,並將其添加到imports數組中。 業力錯誤如下所示:
Chrome 52.0.2743 (Mac OS X 10.12.0) App: TrackBudget should create the app FAILED
Failed: Error in ./AppComponent class AppComponent_Host - inline template:0:0 caused by: No provider for Http!
Error: No provider for Http!
at NoProviderError.Error (native)
at NoProviderError.BaseError [as constructor] (webpack:/Users/ChrisGaona%201/budget-tracking/~/@angular/core/src/facade/errors.js:24:0 <- src/test.ts:2559:34)
at NoProviderError.AbstractProviderError [as constructor] (webpack:/Users/ChrisGaona%201/budget-tracking/~/@angular/core/src/di/reflective_errors.js:42:0 <- src/test.ts:15415:16)
at new NoProviderError (webpack:/Users/ChrisGaona%201/budget-tracking/~/@angular/core/src/di/reflective_errors.js:73:0 <- src/test.ts:15446:16)
at ReflectiveInjector_._throwOrNull (webpack:/Users/ChrisGaona%201/budget-tracking/~/@angular/core/src/di/reflective_injector.js:761:0 <- src/test.ts:26066:19)
at ReflectiveInjector_._getByKeyDefault (webpack:/Users/ChrisGaona%201/budget-tracking/~/@angular/core/src/di/reflective_injector.js:789:0 <- src/test.ts:26094:25)
at ReflectiveInjector_._getByKey (webpack:/Users/ChrisGaona%201/budget-tracking/~/@angular/core/src/di/reflective_injector.js:752:0 <- src/test.ts:26057:25)
at ReflectiveInjector_.get (webpack:/Users/ChrisGaona%201/budget-tracking/~/@angular/core/src/di/reflective_injector.js:561:0 <- src/test.ts:25866:21)
at TestBed.get (webpack:/Users/ChrisGaona%201/budget-tracking/~/@angular/core/bundles/core-testing.umd.js:1115:0 <- src/test.ts:5626:67)
Chrome 52.0.2743 (Mac OS X 10.12.0): Executed 1 of 1 (1 FAILED) ERROR (0.229 secs / 0.174 secs)
這是我的app.component.ts文件:
import {Component} from '@angular/core';
import {Budget} from "./budget";
import {BudgetService} from "./budget.service";
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
providers: [BudgetService]
})
export class AppComponent {
title = 'Budget Tracker';
budgets: Budget[];
selectedBudget: Budget;
constructor(private budgetService: BudgetService) { }
ngOnInit(): void {
this.budgetService.getBudgets()
.subscribe(data => {
this.budgets = data;
console.log(data);
this.selectedBudget = data[0];
console.log(data[0]);
});
}
}
這是我的簡單規范:
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('App: TrackBudget', () => {
beforeEach(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
]
});
});
it('should create the app', async(() => {
let fixture = TestBed.createComponent(AppComponent);
let app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
});
該錯誤似乎是由我的服務引起的,可以在這里看到:
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';
import {Budget} from "./budget";
@Injectable()
export class BudgetService {
constructor(public http: Http) { }
getBudgets() {
return this.http.get('budget.json')
.map(response => <Budget[]>response.json().budgetData);
}
}
如果我從服務中刪除constructor(public http: Http) { }
語句,測試傳遞正常,但隨后應用程序在瀏覽器中失敗。 我已就此做了大量研究,但未能找到解決方案。 任何幫助將不勝感激!!
TestBed
的目的是從頭開始為測試環境配置@NgModule
。 因此,目前您配置的所有內容都是AppComponent
, 沒有其他內容(除了已經在@Component.providers
聲明的服務之外)。
我強烈建議你這樣做,而不是試圖像在真實環境中那樣配置所有內容,只是模擬BudgetService
。 嘗試配置Http
並模擬它並不是最好的主意,因為您希望在單元測試時盡可能保持外部依賴性盡可能輕。
這是你需要做的
如果你真的想要使用真實服務和Http
,那么你需要准備在MockBackend
上模擬連接。 您無法使用真正的后端,因為它依賴於平台瀏覽器。 舉個例子,看看這篇文章 。 在測試組件時,我個人認為這不是一個好主意。 在測試您的服務時,您應該這樣做。
警告 :此解決方案僅在您要測試靜態結構時才有效。 如果您的測試實際上進行了服務調用(並且您最好還有一些測試),它將無法工作。
您的測試使用自己的模塊定義,測試模塊,而不是您的AppModule。 所以你必須在那里導入HttpModule:
TestBed.configureTestingModule({
imports: [
HttpModule
],
declarations: [
AppComponent
]
});
您還可以導入AppModule:
TestBed.configureTestingModule({
imports: [
AppModule
]
});
這樣做的好處是您不必在許多地方添加新組件和模塊。 它更方便。 另一方面,這不太靈活。 您可能在測試中導入的數量超出了您的預期。
此外,您具有從低級組件到整個AppModule的依賴關系。 事實上,這是一種循環依賴,通常是一個壞主意。 所以在我看來,你應該只為那些對你的應用程序至關重要的高級組件這樣做。 對於可能可重用的更多低級組件,最好在測試規范中明確列出所有依賴項。
警告 :只有在您沒有真正打電話給您的服務時才會有效。 僅當您要測試靜態結構時,它才有效。
只想添加Angular版本4(可能更高版本),你應該將HttpClientModule
導入你的測試床,這樣它看起來像這樣:
import { HttpClientModule } from '@angular/common/http';
describe('BuildingService', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HttpClientModule],
providers: [BuildingService]
});
});
it('should be created 2', inject([BuildingService], (service: BuildingService) => {
expect(service).toBeTruthy();
}));
}
小心 :請參閱頂部注意
在app.module.ts中導入HttpModule,它將解決您的問題。
import { HttpModule } from '@angular/http';
@NgModule({
imports: [HttpModule]
})
...
如peeskillet的回答所述, 模擬服務的另一種方法是使用由角度提供的模擬后端 。
API文檔包含以下示例:
import {Injectable, ReflectiveInjector} from '@angular/core';
import {async, fakeAsync, tick} from '@angular/core/testing';
import {BaseRequestOptions, ConnectionBackend, Http, RequestOptions} from '@angular/http';
import {Response, ResponseOptions} from '@angular/http';
import {MockBackend, MockConnection} from '@angular/http/testing';
const HERO_ONE = 'HeroNrOne';
const HERO_TWO = 'WillBeAlwaysTheSecond';
@Injectable()
class HeroService {
constructor(private http: Http) {}
getHeroes(): Promise<String[]> {
return this.http.get('myservices.de/api/heroes')
.toPromise()
.then(response => response.json().data)
.catch(e => this.handleError(e));
}
private handleError(error: any): Promise<any> {
console.error('An error occurred', error);
return Promise.reject(error.message || error);
}
}
describe('MockBackend HeroService Example', () => {
beforeEach(() => {
this.injector = ReflectiveInjector.resolveAndCreate([
{provide: ConnectionBackend, useClass: MockBackend},
{provide: RequestOptions, useClass: BaseRequestOptions},
Http,
HeroService,
]);
this.heroService = this.injector.get(HeroService);
this.backend = this.injector.get(ConnectionBackend) as MockBackend;
this.backend.connections.subscribe((connection: any) => this.lastConnection = connection);
});
it('getHeroes() should query current service url', () => {
this.heroService.getHeroes();
expect(this.lastConnection).toBeDefined('no http service connection at all?');
expect(this.lastConnection.request.url).toMatch(/api\/heroes$/, 'url invalid');
});
it('getHeroes() should return some heroes', fakeAsync(() => {
let result: String[];
this.heroService.getHeroes().then((heroes: String[]) => result = heroes);
this.lastConnection.mockRespond(new Response(new ResponseOptions({
body: JSON.stringify({data: [HERO_ONE, HERO_TWO]}),
})));
tick();
expect(result.length).toEqual(2, 'should contain given amount of heroes');
expect(result[0]).toEqual(HERO_ONE, ' HERO_ONE should be the first hero');
expect(result[1]).toEqual(HERO_TWO, ' HERO_TWO should be the second hero');
}));
it('getHeroes() while server is down', fakeAsync(() => {
let result: String[];
let catchedError: any;
this.heroService.getHeroes()
.then((heroes: String[]) => result = heroes)
.catch((error: any) => catchedError = error);
this.lastConnection.mockRespond(new Response(new ResponseOptions({
status: 404,
statusText: 'URL not Found',
})));
tick();
expect(result).toBeUndefined();
expect(catchedError).toBeDefined();
}));
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.