Javascript Angular Unit Test MockService仍然抛出无法读取属性';订阅';未定义的

Javascript Angular Unit Test MockService仍然抛出无法读取属性';订阅';未定义的,javascript,angular,typescript,unit-testing,karma-jasmine,Javascript,Angular,Typescript,Unit Testing,Karma Jasmine,我又一次被困在这个问题上了,虽然这个线程()和这个差不多,但它仍然不能解决我的问题 我有一个组件可以调用ngOnInit上的简单函数: ngOnInit() { this.getModules(); } getModules() { this.configService.getModulesToDisplay().subscribe(modules => { this.modulesToDisplay = modules; } ); } 我想测试两件事: 是

我又一次被困在这个问题上了,虽然这个线程()和这个差不多,但它仍然不能解决我的问题

我有一个组件可以调用ngOnInit上的简单函数:

ngOnInit() {
  this.getModules();
}

getModules() {
  this.configService.getModulesToDisplay().subscribe(modules => {
    this.modulesToDisplay = modules;
    }
  );
}
我想测试两件事:

是否在
ngOnInit

this.modulesToDisplayed
在得到某些结果时是否重新分配

因此,我模拟了我的服务,但第一次测试仍然失败,类型错误为“无法读取未定义的”属性“subscribe”

我将我的模拟服务移动到了所有不同的区域,因为我猜当测试开始构建组件时,模拟不可用。但我还是不明白。我的测试看起来像:

describe('NavigationComponent', () => {
  let component: NavigationComponent;
  let fixture: ComponentFixture<NavigationComponent>;
  let configServiceMock: any;

  beforeEach(async(() => {

    configServiceMock = jasmine.createSpyObj('ConfigService', ['getModulesToDisplay']);
    configServiceMock.getModulesToDisplay.and.returnValue( of(['module1', 'module2']) );

    TestBed.configureTestingModule({
      declarations: [
        NavigationComponent
      ],
      imports: [
        RouterTestingModule,
        HttpClientTestingModule
      ],
      providers: [
        { provide: ConfigService, useValue: configServiceMock },
      ],
      schemas: [ CUSTOM_ELEMENTS_SCHEMA ]
    }).compileComponents();

  beforeEach(() => {
    // configServiceMock.getModulesToDisplay.and.returnValue( of(['module1', 'module2']) );
    fixture = TestBed.createComponent(NavigationComponent);
    component = fixture.componentInstance;
  });
  }));
第一个测试失败,出现无法读取订阅错误。但是第二个过程使用了正确的mockvalue

  it('should assign result to modulesToDisplay', () => {
    component.getModules();
    expect(component.modulesToDisplay.length).toBeGreaterThan(0);
  });

非常感谢任何关于我还缺少什么的提示

不要在每个
spec
文件中编写jasmine
spy
,而是创建一个可重用的
Mock
文件

export class MockConfigService{
   getModulesToDisplay(){
     return of({
         // whatever module object structure is
     })
   }
}
it
块中:

    it('should call getModulesToDisplay one time on ngOninit()', () => {
      spyOn(component, 'getModules').and.callThrough();
      component.ngOnInit();
      expect(component.getModules).toHaveBeenCalledTimes(1);
    });

“是否在ngOnInit上调用getModules”不是您想要测试的内容。这是组件的一个内部细节,
getModules
可能是私有的,您需要测试它是否与协作者的testdouble正确交互。不要直接调用该方法,只通过
ngOnInit
调用它,这样您就可以自由地在类中进行重构。谢谢您的回答。我明白你的意思,将删除ngOnInit测试。尽管我仍然想知道为什么我在问题中发布的链接示例中使用了它,但在我的设置中却没有。我仍然很想知道,当测试编译组件时,模拟服务的返回值是否已经可用。@BreadcrumbPie:你尝试过我的可重用方法吗?我看到投了反对票。如果你觉得这不相关,一定要让我知道,我会删除的。对不起,我的回答耽搁了。我花了一段时间做各种各样的测试(我以前也看过你的博客)。我认为我最大的问题是找出它真正需要什么测试。所以我决定根本不参加ngOninit测试
    it('should call getModulesToDisplay one time on ngOninit()', () => {
      spyOn(component, 'getModules').and.callThrough();
      component.ngOnInit();
      expect(component.getModules).toHaveBeenCalledTimes(1);
    });