2017-03-15 17 views
0

私はAngularで小さなおもちゃのアプリを構築しています。その中には、次のクラスがあります(ProductDetailComponentおよびProductService)。このサービスには、製品のhttp GETリクエストを作成するためのメソッドが含まれています。コンパニオンは、製品の詳細を表示し、このサービスを使用して製品情報を取得します。アプリケーション(とそのサービス内のサービス)にHttpModuleを追加した後、私のコンポーネントテストは失敗して、 "エラー:Httpのプロバイダがありません!"と言います。角度:依存関係のないプロバイダ

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

しようとする:NgModuleでプロバイダーとしてごNgModule

  • セットProductServiceへ

    • 輸入HttpModuleまたはProductDetailComponent例えば

    : 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プロバイダをあなたのprに追加する必要がありますオービルダーのプロパティ:

    プロバイダー:[ProductService]

    関連する問題