繁体   English   中英

Angular 9 测试组件依赖于可观察的服务 - 无法读取未定义的属性“订阅”

[英]Angular 9 testing component dependant on service with observable - Cannot read property 'subscribe' of undefined

我正在尝试测试正在使用服务的组件。 我使用 spy 来模拟它,但每次我运行测试时它都会失败并出现异常:

无法读取未定义的属性“订阅”

我的测试如下所示:

 describe('FilmOverviewComponent', () => { let component: FilmOverviewComponent; let fixture: ComponentFixture<FilmOverviewComponent>; let filmsServiceSpy: jasmine.SpyObj<FilmsService>; beforeEach(async(() => { const spy = jasmine.createSpyObj('FilmsService', ['searchFilmByID'] ); TestBed.configureTestingModule({ declarations: [ FilmOverviewComponent ], providers: [ {provide: AppTitleService, useValue: {getTitle: () => 'title'}}, {provide: ActivatedRoute, useValue: {params: of({id: 123})} }, {provide: FilmsService, useValue: spy} ] }).compileComponents(); filmsServiceSpy = TestBed.get(FilmsService); })); beforeEach(() => { filmsServiceSpy.searchFilmByID.and.returnValue(Observable.create([{title: "", year: ""}])); fixture = TestBed.createComponent(FilmOverviewComponent); component = fixture.componentInstance; fixture.detectChanges(); }); it('should create', () => { expect(component).toBeTruthy(); }); });

服务中使用的方法:

 searchFilmByID(movieID: string): Observable<Film> { return this.http.get<Film>(this.getUrlWithID(movieID)); } private getUrlWithID(movieID: string) { return 'api/externalfilms/film/' + movieID; }

我不知道如何解决这个问题。 我怀疑它可以通过某种订阅方法的 mocking 来解决,但我完全失败了。

提前谢谢你的帮助!

错误来自this.http.get<Film>... 有2种方法可以解决。

第一种方式 - 模拟 http 客户端服务并调用假

describe('FilmOverviewComponent', () => {
  let component: FilmOverviewComponent;
  let fixture: ComponentFixture<FilmOverviewComponent>;

  let filmsService: FilmsService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ FilmOverviewComponent ],
      imports: [ HttpClientTestingModule ],
      providers: [
        {provide: AppTitleService, useValue: {getTitle: () => 'title'}},
        {provide: ActivatedRoute, useValue: {params: of({id: 123})} },
        FilmsService
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    filmsService = TestBed.inject(FilmsService);

    /* Mock response */
    const httpClient: HttpClient = TestBed.inject(HttpClient);
    spyOn(httpClient, 'get').and.callFake(() => of({title: "", year: ""}));

    fixture = TestBed.createComponent(FilmOverviewComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
   expect(component).toBeTruthy();
  });
});

第二种方式——调用假服务方法

const FilmsServiceStub = jasmine.createSpyObj('FilmsService', ['searchFilmByID']);

describe('FilmOverviewComponent', () => {
  let component: FilmOverviewComponent;
  let fixture: ComponentFixture<FilmOverviewComponent>;

  let filmsService: FilmsService;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ FilmOverviewComponent ],
      providers: [
        {provide: AppTitleService, useValue: {getTitle: () => 'title'}},
        {provide: ActivatedRoute, useValue: {params: of({id: 123})} },
        {provide: FilmsService, useValue: FilmsServiceStub}
      ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    filmsService = TestBed.inject(FilmsService);

    /* Mock response */
    spyOn(filmsService, 'searchFilmByID').and.callFake(() => of({title: "", year: ""}));

    fixture = TestBed.createComponent(FilmOverviewComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should create', () => {
   expect(component).toBeTruthy();
  });
});

暂无
暂无

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

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