javascript - Angular 9 测试组件依赖于可观察的服务 - 无法读取未定义的属性 'subscribe'

标签 javascript angular typescript karma-jasmine

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

Cannot read property 'subscribe' of undefined

我的测试是这样的:

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;
  }

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

提前感谢您的帮助!

最佳答案

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

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

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();
  });
});

关于javascript - Angular 9 测试组件依赖于可观察的服务 - 无法读取未定义的属性 'subscribe',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62713828/

相关文章:

javascript - Node.js 需要 webpack 模块

javascript - 使用 Ionic 3 应用程序输入掩码

Angular 5 使用 blob 响应和 json 错误管理 http get

angular - 如何按选定的值过滤数据?

angular - NPM 包 : Referring to assets within the package

javascript - 如何更改输入值onfocus和onblur(无jquery)

javascript - 使用其他指令的指令 - AngularJS

reactjs - event.currentTarget.name 返回为 currentTarget

javascript - 我的透视投影矩阵有什么问题?

Angular 2(更改)事件未触发