2017-03-15 52 views
0

我正在Angular中構建一個小型玩具應用程序,其中包含以下類別(和ProductService)。該服務包含一個爲產品發出http GET請求的方法。 compnent顯示產品的詳細信息,並使用該服務檢索產品信息。在將HttpModule添加到應用程序(以及其中的服務)後,我的組件測試失敗,並說「錯誤:沒有提供程序Http!」。Angular:沒有依賴性依賴的提供者

如果我導入HttpModule,測試再次通過。然而,我很困惑,爲什麼它首先需要HttpModule,因爲這是一個ProductService依賴關係,並且我正在使用提供者嘲笑ProductService

所以我的問題總之是爲什麼測試告訴我,當被測試的類不使用它時,我需要這種依賴關係?

產品detail.component.ts

import {Component, OnInit} from '@angular/core'; 
import {ActivatedRoute, Params} from "@angular/router"; 
import {ProductService} from "../product.service"; 
import {Product} from "../product"; 
import 'rxjs/add/operator/switchMap'; 

@Component({ 
    selector: 'app-product-detail', 
    templateUrl: './product-detail.component.html', 
    styleUrls: ['./product-detail.component.css'], 
    providers: [ProductService] 
}) 
export class ProductDetailComponent implements OnInit { 
    product: Product; 

    constructor(
    private productService: ProductService, 
    private route: ActivatedRoute, 
) { } 

    ngOnInit() { 
    this.route.params 
     .switchMap((params: Params) => this.productService.getProduct(+params['id'])) 
     .subscribe(product => this.product = product); 
    } 
} 

product.service.ts

import {Injectable} from "@angular/core"; 
import {Product} from "./product"; 
import {Http} from "@angular/http"; 
import "rxjs/add/operator/toPromise"; 

@Injectable() 
export class ProductService { 
    private products: Product[]; 

    constructor(private http: Http) { } 

    getProducts(): Promise<Product[]> { 
    return this.http 
     .get('/api/products/') 
     .toPromise() 
     .then(response => response.json() as Product[]) 
     .catch(error => { 
     console.error('An error occurred', error); 
     return Promise.reject(error.message || error) 
     }); 
    } 

    getProduct(id: number): Promise<Product> { 
    return this.http 
     .get(`/api/products/${id}`) 
     .toPromise() 
     .then(response => response.json() as Product) 
     .catch(error => { 
     console.error('An error occurred', error); 
     return Promise.reject(error.message || error) 
     }); 
    } 
} 

產品detail.component.spec.ts:

import {async, ComponentFixture, TestBed} from "@angular/core/testing"; 
import {ProductDetailComponent} from "./product-detail.component"; 
import {ActivatedRoute} from "@angular/router"; 
import {Observable} from "rxjs"; 
import {ProductService} from "../product.service"; 
import {Product} from "../product"; 
import {By} from "@angular/platform-browser"; 
import {DebugElement} from "@angular/core"; 
import {HttpModule} from "@angular/http"; 

describe('ProductDetailComponent',() => { 
    let component: ProductDetailComponent; 
    let fixture: ComponentFixture<ProductDetailComponent>; 
    let debugElement: DebugElement; 
    let element: HTMLElement; 

    beforeEach(async(() => { 
    TestBed.configureTestingModule({ 
     declarations: [ProductDetailComponent], 
     //imports: [HttpModule], //un-commenting this fixes the breakages 
     providers: [{ 
     provide: ActivatedRoute, 
     useValue: {params: Observable.from([{'id': 1}])}, 
     }, { 
     provide: ProductService, 
     useValue: { 
      getProduct: (id: number) => Promise.resolve(new Product(id, 'Example Product Name', 20)) 
     } 
     }] 
    }) 
     .compileComponents(); 
    })); 

    beforeEach(() => { 
    fixture = TestBed.createComponent(ProductDetailComponent); 
    component = fixture.componentInstance; 
    fixture.detectChanges(); 
    }); 

    it('should create',() => { 
    expect(component).toBeTruthy(); 
    }); 

    it('should be stable',() => { 
    fixture.whenStable().then(() => { 
     expect(fixture.isStable()).toBe(true); 
    }); 
    }); 

    it('should display the title',() => { 
    fixture.whenStable().then(() => { 
     debugElement = fixture.debugElement.query(By.css('.name')); 
     element = debugElement.nativeElement; 
     expect(element.textContent).toEqual('Example Product Name') 
    }); 
    }); 

    it('should display the price',() => { 
    fixture.whenStable().then(() => { 
     debugElement = fixture.debugElement.query(By.css('.span')); 
     element = debugElement.nativeElement; 
     expect(element.textContent).toEqual('$ 20.0') 
    }); 
    }); 
}); 

回答

0

嘗試:

  • 進口HttpModuleNgModule
  • 集ProductService作爲一個供應商在NgModuleProductDetailComponent

例如: product.module.ts

import { HttpModule } from '@angular/http'; 
import { ProductDetailComponent } from './product-detail.component'; 
import { ProductService } from 'product.service'; 

@NgModule({ 
    imports: [ 
    HttpModule, 
    NgbModule.forRoot(), 
    ], 
    declarations: [ 
    ProductDetailComponent 
    ], 
    providers: [ 
    ProductService 
    ], 
}) 
export class ProductModule { } 
0

在您的模塊中,您必須將ProductService供應商添加到您的公關oviders物業:

提供者:[ProductService]