Jasmine单元测试订阅构造函数中的服务主题的angular组件提供了无法读取未定义的subscribe属性

Jasmine单元测试订阅构造函数中的服务主题的angular组件提供了无法读取未定义的subscribe属性,angular,unit-testing,jasmine,rxjs,Angular,Unit Testing,Jasmine,Rxjs,我正在尝试为下面的组件编写一个测试 import { Component, OnInit } from '@angular/core'; import { Router } from '@angular/router'; import { LoginService } from '../../services/login.service'; @Component({ selector: 'app-banner', templateUrl: './banner.component.ht

我正在尝试为下面的组件编写一个测试

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';

import { LoginService } from '../../services/login.service';

@Component({
  selector: 'app-banner',
  templateUrl: './banner.component.html',
  styleUrls: ['./banner.component.css']
})
export class BannerComponent implements OnInit {

  isLoggedIn = false;
  user: User = new User('');

  constructor(
    private loginService: LoginService,
    private router: Router
  ) {
    this.loginService.userWatcher.subscribe(res => {
      this.isLoggedIn = true;
      this.user.oun = res;
    });
  }
...

}
然而,当我编写测试时,我得到了这个错误

TypeError: Cannot read property 'subscribe' of undefined
以下是规范文件:

import { LoginServiceSpy } from '../../services/mock/login.service.spy.spec';
describe('BannerComponent', () => {
  let component: BannerComponent;
  let fixture: ComponentFixture<BannerComponent>;
  const loginService = LoginServiceSpy;
  const user = 'testuser';

  beforeEach(async(() => {

    TestBed.configureTestingModule({
      declarations: [
        BannerComponent,
        MockComponent(SpinnerComponent)
      ],
      imports: [
        FormsModule,
        NgbModule.forRoot(),
        RouterTestingModule
      ],
      providers: [
        { provide: LoginService, useValue: loginService }
      ]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(BannerComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  describe('Unit Tests', () => {

    beforeEach(() => {
      localStorage.setItem('currentUser', user);
      loginService.callNextUserWatcher.and.returnValue(asyncData('test'));
    });
...
我从jasmine那里得到了回应: 无法读取未定义的属性和

任何帮助都将不胜感激。

这可能是因为fixture.detect在每次运行之前都会在外部进行更改,并将加载您的组件。那时你的间谍还没有被创造出来,因此你就犯了这个错误

每次之前把你的间谍移到外边

或不运行fixture.detectChanges;从外到前


第一次检测更改应在所有应用程序数据初始化后发生。

如果未创建间谍,错误将是无法读取未定义的userWatcher,你不这样认为吗?间谍是被创造出来的,而ùserWatcher的值没有定义这一事实是另一个问题。没有,因为他一开始就声明了loginService。但它不是用间谍初始化的。这就是问题所在。this.loginService已定义,但this.loginService.userWatcher未定义,因此无法在未定义的userWatcher上读取subscribe。spy指的是在测试床配置期间通过ValueProvider提供的值。我想你指的是ùserWatcher财产。是的,你可能就在这里。我花了一些时间才意识到。而且它与正在被创造的间谍无关。我想我必须在这里删除我的答案。找到答案成功了吗?我试过你的建议,但你是对的,没有用
import { createSpyFromClass, Spy } from 'jasmine-auto-spies';
import { LoginService } from '../login.service';

export const LoginServiceSpy: Spy<LoginService> = createSpyFromClass(LoginService);
loginService.userWatcher.and.returnValue(Observable.of('test'));
beforeEach(() => {
    fixture = TestBed.createComponent(BannerComponent);
    component = fixture.componentInstance;
    loginService.callNextUserWatcher.and.returnValue(asyncData('test')); // spy created before detect change
    fixture.detectChanges();
  });
 beforeEach(() => {
    fixture = TestBed.createComponent(BannerComponent);
    component = fixture.componentInstance;
   // fixture.detectChanges();  -- remove this line
  });