简体   繁体   English

如何使用Karma为Angular测试创建虚假服务

[英]How to create a fake service for Angular testing using Karma

I try to create a fake service matching my AppLoaderService for karma testing of my Angular application. 我尝试创建一个与我的AppLoaderService匹配的虚假服务,以对Angular应用程序进行业力测试。

I have a service which handle loader visibility state over my application. 我有一个服务,可以处理我的应用程序中的加载程序可见性状态。 It's used in components this way: 它在组件中的使用方式如下:

  • The main component subscribe the state of loader to display or not the loader 主要组件订阅加载程序的状态以显示或不显示加载程序
  • Child components and other services can trigger the emitChange function to change visibility state over the service 子组件和其他服务可以触发emitChange函数来更改服务的可见性状态

Here is the service: 这是服务:

import { Injectable } from '@angular/core';
import { Observable } from 'rxjs/Rx';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';

@Injectable()
export class AppLoaderService {
  private isLoaderVisible = new BehaviorSubject<boolean>(false);

  changeLoaderState$ = this.isLoaderVisible.asObservable();

  emitChange(state: any) {
    this.isLoaderVisible.next(state);
  }    
}

The fact is this service will be changed over time by the team. 事实是,该服务将随着时间的推移由团队更改。

And I don't really care about testing the fact the logic of AppLoaderService will "work" at component testing level. 而且我并不真正关心测试AppLoaderService的逻辑将在组件测试级别“起作用”的事实。 I want only be able to test, at component level, subscription to service (for main component) and returns initial service value and that emitChange() has been triggered at some moments in my component life. 我只希望能够在组件级别测试对服务的订阅(对于主要组件)并返回初始服务值,并且我的组件生命中的某个时刻已经触发了emitChange()

So in order not to be dependant on the service itself, maybe I can stub this service to then, in my component tests, be able to use this stub with: 因此,为了不依赖服务本身,也许我可以对该服务进行存根,然后在我的组件测试中,可以将该存根与以下项一起使用:

providers: [
  {provide: AppLoaderService, useClass: AppLoaderServiceStub}
]

But I struggle defining a proper stubs without rewriting the whole service. 但是我很难定义一个适当的存根而不重写整个服务。

Do you have any idea on how I can achieve this? 您对我如何实现这一目标有任何想法吗? Especially the fact one of my component is subscribing to changeLoaderState$ . 特别是我的组件之一正在订阅changeLoaderState$

The key point when stubbing is that the stub needs to implement the public API that the component under test cares about . 存根的关键点是存根需要实现被测组件关心的公共API。

From your example code, you need an emitChange(state: any) method on your stub. 从示例代码中,您的存根上需要一个emitChange(state: any)方法。 If you don't care at all whether it gets called or not, then you can just leave that method with an empty body. 如果您根本不关心它是否被调用,则可以将该方法留空。

export class AppLoaderServiceStub {

  emitChange(state: any) {
  }    
}

(I'm making the assumption that the observable property on the service is only being used by your Loader component, not by the other components and services of your app - if that assumption is false, you'd have to stub that observable as well). (我假设服务的observable属性仅由您的Loader组件使用,而不由应用程序的其他组件和服务使用-如果该假设为假,则您也必须对可观察的属性进行存根)。

EDIT: 编辑:

Since you need the changeLoaderState$ observable, then stub that as well - 由于您需要changeLoaderState $可观察到,因此也要存根-

export class AppLoaderServiceStub {

  changeLoaderState$ = Observable.of({ }) // or whatever dummy state value you want to use
  emitChange(state: any) {}    
} 

Note that Observable.of will emit its values and then complete. 请注意, Observable.of将发出其值,然后完成。 If you don't want a completion event to trigger, you might want Observable.never . 如果您不希望触发完成事件,则可能需要Observable.never If I am understanding your usage correctly though, I doubt the distinction matters. 如果我正确理解了您的用法,我怀疑区别是否重要。

PS. PS。 don't forget to import the of operator: 不要忘了导入of操作:

import 'rxjs/add/observable/of';

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM