【问题标题】:Cannot Read Property 'subscribe' of Angular Test Mock无法读取 Angular 测试模拟的属性“订阅”
【发布时间】:2017-10-03 10:48:36
【问题描述】:

我正在尝试对具有注入服务的 Angular 组件进行单元测试。在组件的构造函数中,调用注入服务的一个方法,该方法返回一个 Observable。我试图在组件的单​​元测试中模拟该服务,但我一直遇到此错误:TypeError: Cannot read property 'subscribe' of undefined

我尝试通过以下方式模拟服务:

const serviceStub = {
  getObservable: () => { return {subscribe: () => {}}; },
};

beforeEach(async(() => {
  TestBed.configureTestingModule({
    providers: [
      {provide: MyService, useValue: serviceStub}
    ]
})


it('should create', () => {
  spyOn(serviceStub, 'getObservable').and.returnValue({subscribe: () => {}});
  expect(component).toBeTruthy();
});

感觉好像我错过了一些明显的东西。有人能指出来吗?

更新

即使我在我的测试平台提供程序中注入实际服务,我也会收到此错误。

组件的构造函数如下所示:

private _subscription: Subscription;

constructor(private _service: MyService) {
  this._subscription = _service.getObservable().subscribe(console.log);
}

【问题讨论】:

  • 所有代码都粘贴了吗?
  • 该错误表明something.subscribe(),未定义的东西。它应该有代码行号。请检查一下。
  • 嗯,这是 Angular,所以它不像查找行号那么简单。这是我为你准备的:at new ApplicationRef_ (webpack:///~/@angular/core/@angular/core.es5.js:4932:0 <- src/renderer/test.ts:5387:37)。我意识到问题在于“某事”是undefined。我已经在上面解释了我为解决这个问题所做的工作。
  • 来自webpack,所以是编译错误?不是运行时错误?
  • 运行ng test时出现错误。

标签: angular dependency-injection jasmine mocking rxjs


【解决方案1】:

使用inject 注入服务并模拟它而不是存根

it('should create', inject([MyService], (myService: MyService) => {
  spyOn(myService, 'getObservable').and.returnValue({subscribe: () => {}});
  expect(component).toBeTruthy();
}));

这里是完整版:

组件:

@Component({
  selector: 'my-cmp',
  template: 'my cmp {{x}}'
})
export class MyComponent {
  x;

  constructor(private myService: MyService) {
    this.myService.getObservable()
      .subscribe(x => {
        console.log(x);
        this.x = x;
      });
  }
}

测试:

   describe('my component test', () => {
    let fixture: ComponentFixture<MyComponent>, comp: MyComponent, debugElement: DebugElement, element: HTMLElement;

    beforeEach(async(() => {
      TestBed.configureTestingModule({
        declarations: [MyComponent],
        providers: [MyService]
      });
    }));

    beforeEach(() => {
      fixture = TestBed.createComponent(MyComponent);
      comp = fixture.componentInstance;
      debugElement = fixture.debugElement;
      element = debugElement.nativeElement;
    });

    it('should create', inject([MyService], (myService: MyService) => {
      expect(comp).toBeTruthy();
    }));

    it('should set value', async(inject([MyService], (myService: MyService) => {
      spyOn(myService, 'getObservable').and.returnValue(Observable.of(1));

      fixture.detectChanges();

      fixture.whenStable().then(() => {
        expect(comp.x).toEqual(1);
      });
    })));
  });

【讨论】:

  • 感谢您的回复,朱莉娅!我期待着一回到家就尝试一下!
  • 欢迎。让我知道。我有很多类似的测试
  • 我更新了答案。这个对我有用。请再试一次。
  • 感谢您的跟进,但不幸的是,它仍然失败并出现同样的错误。我更加努力地查看了输出,似乎错误来自对TestBed.createComponent 的调用,这使得您的建议没有帮助更有意义的事实,至少......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-12-13
  • 2017-06-28
  • 1970-01-01
  • 2019-04-06
  • 1970-01-01
  • 1970-01-01
  • 2017-03-01
相关资源
最近更新 更多