【问题标题】:Mocking an Angular Service that has RxJS Observables for testing模拟具有 RxJS Observables 的 Angular 服务进行测试
【发布时间】:2018-03-24 10:25:21
【问题描述】:

我希望模拟我在 Angular 应用程序中构建的服务。我的服务如下:

@Injectable()
export class WizardDialogNavigationService {

  public navAction$: Observable<any>;
  public navActionSubject: BehaviorSubject<any> = new BehaviorSubject(null);

  constructor() {
    this.navAction$ = this.navActionSubject.asObservable();
  }

  public navAction(action: string): void {
    this.navActionSubject.next(action);
  }
}

我在一个组件中使用它,我将它注入到我的构造函数中,然后将它添加到 OnInit 方法中的订阅中,例如(组件代码) - 我的代码在下面,请注意我只添加相关的内容。

private navSubscription: Subscription = new Subscription();

constructor(private wizardDialogNavigationService: WizardDialogNavigationService) {}

public ngOnInit(): void {
       this.navSubscription.add(this.wizardDialogNavigationService.navAction$.subscribe((direction) => {
      this.moveMaterialStepper(direction);
    }));
  }

我需要模拟我的服务来测试我的组件,但是我以错误的方式解决了这个问题,例如,我像这样创建模拟服务......

class MockWizardDialogNavigationService {

public navAction$: Observable<any>;
public navActionSubject: BehaviorSubject<any> = new BehaviorSubject(null);
// this is wrong?
constructor() {
    this.navAction$ = this.navActionSubject.asObservable();
  }

  public navAction(action: string): void {
    // how do I mock a .next?
  }
}

该类位于我的测试文件 (spec.ts) 的顶部,然后我将其添加到提供程序对象中

{provide: WizardDialogNavigationService, useValue: MockWizardDialogNavigationService},

然后添加一个存根,以便我可以在调用 navAction 方法时进行监听:

stubWizardService = sinon.createStubInstance(WizardDialogNavigationService);

但是我觉得这是错误的,我确信我是如何在模拟中声明 navAction$ 可观察的,并且在运行我的测试时出现以下错误:

Uncaught (in promise): TypeError: undefined is not an object (评估“this.wizardDialogNavigationService.navAction$.subscribe”)

有人可以解释我需要做什么来模拟服务并防止错误吗?如果我没有很好地解释自己或需要更多代码,请告诉我。我对测试知之甚少,正在努力学习。

【问题讨论】:

标签: angular unit-testing typescript karma-jasmine sinon


【解决方案1】:

在@jonsharpe 的建议之后,我发现了问题所在 - 我删除了 Mock Service 类并像这样创建了一个存根实例

MockWizardDialogNavigationService = sinon.createStubInstance(WizardDialogNavigationService);

我将服务保存在 providers 数组中

{provide: WizardDialogNavigationService, useValue: MockWizardDialogNavigationService},

然后我像这样声明 navAction$

TestBed.compileComponents().then(() => {
// some code removed
        stubWizardService.navAction$ = Observable.empty();

}); 

一切正常!

【讨论】:

    【解决方案2】:

    模拟服务和服务调用很重要。您不想使用真正的承诺,因为它处理异步并且可能会失败。您可以将错误模拟为。

    这是一个模拟服务的示例。

    it('should mock videos', inject([VideoService], (videoService: VideoService) => { 
            videos = [
                { id: 0,  name: 'Superman' },
                { id: 1, name: 'Superman part 2' }
              ]
            spyOn(videoService, 'videos').and.returnValue(videos); 
            fixture.detectChanges();
            expect(component.getVideoOne()).toContain(Superman);
    
          });
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-01-22
      • 1970-01-01
      • 2011-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-11-29
      相关资源
      最近更新 更多