单位测试spyOn可观察的服务在angular2

时间:2017-02-21 04:33:54

标签: angular typescript unit-testing

我有一个服务(ChildService),它依赖于另一个服务(InteractWithServerService)。后一个服务(InteractWithServerService)用于进行服务器调用并返回一个可观察的" any"类型。为简单起见,我们假设它返回一个可观察的。我正在尝试为ChildService编写单元测试。

ChildService

@Injectable()
export class ApplicationService {
    constructor(private  interactWithServerService:InteractWithServerService){;}

    public GetMeData():string {
        var output:string;       
        this.interactWithServerService.get("api/getSomeData").
           subscribe(response =>{console.log("server response:", response);
           output=response});        
         return output;
    }
}

ServerInteractionService

@Injectable()
export class InteractWithServerService {        
    constructor(private http: Http) {
        ;
    }    
    get(url: string): Observable<any> {        
        return this.http.get(this.url);
    }       
}

当我模拟依赖服务时,测试用例工作正常。即,

class MockInteractWithServerService {
    get() {
        return Observable.of("some text");
    }           
}

describe('Service:ChildService', () => {
    let childService: ChildService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
             { provide: InteractWithServerService, useClass: MockInteractWithServerService },
                ChildService],
        });


    beforeEach(inject([ChildService], (actualService: ChildService) => {
        childService= actualService;        
    }));

    fit('should call server-call testCall()', () => {
        let actualReturnvalue= childService.GetMeData();        
        expect(actualReturnvalue).toBe("some text");
    });
});

上述方法不是优选的,因为我可能最终写作&#34; n&#34; &#34; n&#34;的模拟课程依赖。所以我想用spyOn创建我的单元测试。 但是,测试用例不起作用并抛出&#34;错误:没有Http的提供者!&#34;。虽然我理解错误是什么,但我想知道为什么它被抛出虽然我在监视依赖服务。看起来像是&#34; spyOn&#34;没有用。

describe('Service:ChildService', () => {
    let childService: ChildService;

    beforeEach(() => {
        TestBed.configureTestingModule({
            providers: [
             InteractWithServerService,
                ChildService],
        });

        spyOn(InteractWithServerService.prototype, 'get').and
             .callFake(()=>      
          {return Observable.of("some text");});       
    });
    beforeEach(inject([ChildService], (actualService: ChildService) => {
        childService= actualService;        
    }));

    fit('should call server-call testCall()', () => {
        let actualReturnvalue= childService.GetMeData();        
        expect(actualReturnvalue).toBe("some text");
    });
});

我错过了一些明显的东西吗?

2 个答案:

答案 0 :(得分:17)

  

但是,测试用例不起作用并抛出“错误:Http没有提供者!”。

因为您仍然在<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" android:weightSum="10"> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:orientation="horizontal" android:layout_weight="2" android:gravity="center"> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/make_team_add_player" android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/add_player" android:layout_marginRight="20dp" /> <de.hdodenhof.circleimageview.CircleImageView android:id="@+id/make_team_add_team" android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/add_team" android:layout_marginLeft="20dp" /> </LinearLayout> <LinearLayout android:layout_width="match_parent" android:orientation="vertical" android:layout_height="0dp" android:layout_weight="8" android:id="@+id/make_teams_teamlistView"> <com.dtu.appname.Adapter.AutofitRecyclerView android:layout_width="match_parent" android:layout_height="match_parent" android:id="@+id/make_teams_teamsRecyclerview" android:columnWidth="180dp" android:clipToPadding="false"> </com.dtu.appname_v1.Adapter.AutofitRecyclerView> </LinearLayout> <Button android:layout_width="match_parent" android:layout_height="50dp" android:layout_alignParentEnd="false" android:layout_alignParentBottom="true" android:background="@color/colorPrimary" android:text="Save" android:textColor="@color/colorAccent" android:id="@+id/make_teams_done_b" /> </LinearLayout> 中拥有该服务,所以Angular仍在尝试创建它

providers

你可以做什么而不是创建一个模拟只是做类似的事情

providers: [
 InteractWithServerService,
    ChildService],

这是你使用提供任何对象的providers: [ { provide: InteractWithServerService, useValue: { get: Observable.of(..) } } ] 。这将是注入时使用的值。在上面的例子中,它只是你的模拟方法的一些任意对象。

如果您想进行间谍活动以便提供不同的值,则可以注入useValue,然后执行

InteractWithServerService

你可以做的另一件事是用虚拟对象模拟Http

spyOn(service, 'get').and.returnValue(Observable.of(...))
// do test

现在{ provide: Http, useValue: {} } 将起作用(只是将类添加到您当前拥有的提供程序中)。你可以只是监视它

InteractWithServerService

答案 1 :(得分:1)

使用茉莉2.6.2:get是一个函数,因此您需要在上面的答案中添加箭头函数符号:

providers: [
  { 
    provide: InteractWithServerService,
    useValue: { get: () => Observable.of(..) }
  }
]