如何使用Jasmine测试组件中使用的Angular 2服务

如何使用Jasmine测试组件中使用的Angular 2服务,angular,jasmine,Angular,Jasmine,我正在尝试学习如何使用Jasmine和Angular 2以及Async设置单元测试。我有一个调用服务的组件。但我似乎遇到了障碍。我有如下服务: 项目服务.ts import { Injectable } from "@angular/core"; import { Http, Response } from "@angular/http"; import { Observable } from "rxjs/Observable"; import { Item } from "./item"; i

我正在尝试学习如何使用Jasmine和Angular 2以及Async设置单元测试。我有一个调用服务的组件。但我似乎遇到了障碍。我有如下服务: 项目服务.ts

import { Injectable } from "@angular/core";
import { Http, Response } from "@angular/http";
import { Observable } from "rxjs/Observable";
import { Item } from "./item";
import 'rxjs/add/operator/catch';
import 'rxjs/add/operator/map';

@Injectable()
export class ItemService {
    private baseUrl = 'api/items/';  // web api URL 
    constructor(private http: Http) { }   

    // calls the [GET] /api/items/GetLatest/{n} Web API method to retrieve the latest items. 
    getLatest(num?: number) {
        let url = this.baseUrl + 'GetLatest/';
        if (num != null) { url += num; }
        return this.http.get(url)
            .map(response => response.json())
            .catch(this.handleError);
    }
}
我正在调用组件(项列表.component.ts)中的服务,如下所示:

import { Component, OnInit } from '@angular/core';
import { Item } from './item';
import { ItemService } from './item.service';
import { GridModule } from '@progress/kendo-angular-grid';
import { GroupDescriptor, process } from '@progress/kendo-data-query';
import { SortDescriptor, orderBy } from '@progress/kendo-data-query';
import { GridDataResult } from '@progress/kendo-angular-grid';
import '@telerik/kendo-theme-default/dist/all.css';
@Component({
    selector: 'itemlist',       
    templateUrl: 'someItems.component.html',       

})

export class ItemListComponent implements OnInit {
    selectedItem: Item;
    items: Item[];
    errorMessage: string;
     groups: GroupDescriptor[];
     sort: SortDescriptor[] = [];
     gridView: GridDataResult;
    constructor(private itemService: ItemService) { }

    ngOnInit() {
        this.getLatest();
    }

    getLatest() {
        this.itemService.getLatest(5)
            .subscribe(latestItems => {
                console.log(latestItems);
                this.items = latestItems;
                this.gridView = {
                    data: orderBy(this.items, this.sort),
                    total: this.items.length
                };
            }, error => {
                console.log('error');
                this.errorMessage = <any>error;
            });
    }   

} 
从'@angular/core'导入{Component,OnInit};
从“./Item”导入{Item};
从“./item.service”导入{ItemService};
从“@progress/kendo angular grid”导入{GridModule};
从'@progress/kendo data query'导入{GroupDescriptor,process};
从'@progress/kendo data query'导入{SortDescriptor,orderBy};
从“@progress/kendo angular grid”导入{GridDataResult};
导入'@telerik/kendo-theme-default/dist/all.css';
@组成部分({
选择器:“项目列表”,
templateUrl:'someItems.component.html',
})
导出类ItemListComponent实现OnInit{
选择编辑项:项目;
项目:项目[];
错误消息:字符串;
组:GroupDescriptor[];
排序:SortDescriptor[]=[];
gridView:GridDataResult;
构造函数(私有项服务:项服务){}
恩戈尼尼特(){
这个。getLatest();
}
getLatest(){
this.itemService.getLatest(5)
.订阅(最新订阅=>{
控制台日志(最新版本);
this.items=最新数据;
this.gridView={
数据:orderBy(this.items,this.sort),
总计:this.items.length
};
},错误=>{
console.log('error');
this.errorMessage=错误;
});
}   
} 
这是我的item.component.spec.ts文件

import { async, inject, ComponentFixture, TestBed } from '@angular/core/testing';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { ItemListComponent } from '../App/item-list.component';
import { ItemService } from '../App/item.service';
import { GridModule } from '@progress/kendo-angular-grid';
import { HttpModule, Http } from "@angular/http";
import { Observable } from 'rxjs/Rx';
import 'rxjs/add/observable/of';

class MockMyService {       
    public items: Array<any>;
    public getLatest(num?: number) {
        this.items = [{ Id: 1, Title: "test1", Description: "test12" }]
        return Observable.of(this.items);

    }
}

describe('Component:ItemList', () => {
    let fixture: ComponentFixture<ItemListComponent>;
    let itemService: MockMyService;

    describe('Async', () => {
        beforeEach(async(() => { 
            TestBed.configureTestingModule({
                declarations: [
                    ItemListComponent
                ],
                providers: [
                    //ItemService
                    { provide: ItemService, useClass: MockMyService }
                ],
                imports: [
                    GridModule,HttpModule
                ],
                schemas: [CUSTOM_ELEMENTS_SCHEMA]
            });

            fixture = TestBed.createComponent(ItemListComponent);
            itemService = fixture.debugElement.injector.get(ItemService);   

             spyOn(itemService, 'getLatest')
               .and.returnValue({ subscribe: () => { itemService.items} });                     

            fixture.detectChanges();               

        }));

        afterEach(() => {
            fixture = undefined;//teardown
        });                             

        it('should get items', () => {
             itemService.getLatest();
             expect(fixture.debugElement.componentInstance.items.length).toEqual(1);
        });    

    });
});
从'@angular/core/testing'导入{async,inject,ComponentFixture,TestBed};
从“@angular/core”导入{CUSTOM_ELEMENTS_SCHEMA}”;
从“../App/item list.component”导入{ItemListComponent};
从“../App/item.service”导入{ItemService};
从“@progress/kendo angular grid”导入{GridModule};
从“@angular/Http”导入{HttpModule,Http}”;
从'rxjs/Rx'导入{Observable};
导入“rxjs/add/observable/of”;
类MockMyService{
公共物品:阵列;
public getLatest(num?:编号){
this.items=[{Id:1,标题:“test1”,描述:“test12”}]
(本项目)的可观测收益;
}
}
描述('组件:项目列表',()=>{
let夹具:组件夹具;
让itemService:MockMyService;
描述('Async',()=>{
beforeach(异步(()=>{
TestBed.configureTestingModule({
声明:[
ItemListComponent
],
供应商:[
//项目服务
{provide:ItemService,useClass:MockMyService}
],
进口:[
网格模块,HttpModule
],
模式:[自定义元素\u模式]
});
fixture=TestBed.createComponent(ItemListComponent);
itemService=fixture.debugElement.injector.get(itemService);
spyOn(itemService,'getLatest')
.and.returnValue({subscribe:()=>{itemService.items}});
fixture.detectChanges();
}));
之后(()=>{
fixture=未定义;//拆卸
});                             
它('应该获取项目',()=>{
itemService.getLatest();
expect(fixture.debugElement.componentInstance.items.length).toEqual(1);
});    
});
});
但是测试抛出如下错误- Chrome 57.0.2987(Windows 7 0.0.0)组件:ItemList异步应获取项目失败 TypeError:无法读取未定义的属性“length”
如果有人能帮我,我将不胜感激。

老兄,看看你的逻辑

class MockMyService {       
  public items: Array<any>;
  public getLatest(num?: number) {
    this.items = [{ Id: 1, Title: "test1", Description: "test12" }]
    return Observable.of(this.items);
  }
}

spyOn(itemService, 'getLatest')
  .and.returnValue({ subscribe: () => { itemService.items} }); 
类MockMyService{
公共物品:阵列;
public getLatest(num?:编号){
this.items=[{Id:1,标题:“test1”,描述:“test12”}]
(本项目)的可观测收益;
}
}
spyOn(itemService,'getLatest')
.and.returnValue({subscribe:()=>{itemService.items}});
在spy(它覆盖了real方法)中,您返回的是
itemService.items
,在调用
getLatest
之前,它甚至没有初始化。这就是为什么它没有定义


如果你已经在模仿这些数据了,那就忘了间谍吧。如果你把它拿出来,它应该会起作用。如果要更改每个测试的数据,请将实际值传递给它,而不是使用未初始化的
itemService.items

谢谢peeskillet!!如果我对间谍发表评论,那就行了。要使用间谍,我不需要嘲笑我的服务。然后间谍代码将是spyOn(itemService,'getLatest').and.returnValue(Observable.of([{'Id':1,'Title':'test1','Description':'test12'}])