简体   繁体   中英

Unsubscribing Angular Observable using takeUntil break unit test

I'm trying to correctly unsubscribing Observable in my Angular application using takeUntil() but it seems to break the test.

Chrome 58.0.3029 (Mac OS X 10.12.5) AppComponent should render title in a h1 tag FAILED
Failed: this.appService.getGuides(...).takeUntil is not a function
TypeError: this.appService.getGuides(...).takeUntil is not a function
    at AppComponent.Array.concat.AppComponent.ngOnInit (webpack:///src/app/app.component.ts:28:7 <- src/test.ts:53764:14)
    at checkAndUpdateDirectiveInline (webpack:///~/@angular/core/@angular/core.es5.js:10923:0 <- src/test.ts:11228:19)

This is code:

  export class AppComponent implements OnDestroy, OnInit {
  private ngUnsubscribe: Subject<void> = new Subject<void>();

  title = 'app works!';
  guides: Guide[];

  constructor(private appService: AppService) {
  }

  ngOnInit(): void {
    this.appService.getGuides()
      .takeUntil(this.ngUnsubscribe)
      .subscribe(
        guides => this.setGuides(guides),
        error => this.onError(error)
      );
  }

  ngOnDestroy(): void {
    this.ngUnsubscribe.next();
    this.ngUnsubscribe.complete();
  }

This is the service implementation:

@Injectable()
export class AppService {

  constructor(private http: Http) { }

  getGuides(): Observable<Guide[]> {
    return this.http.get(environment.apiUrl + '/guides')
      .map(this.extractData);
  }

  private extractData(res) {
    if (res.status < 200 || res.status >= 300) {
      throw new Error('Bad response status: ' + res.status);
    }
    return res.json();
  }
}

And this is the test that is failing:

class MockAppService extends AbstractMockObservableService {
  getGuides() {
    return this;
  }
}
describe('AppComponent', () => {
  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [AppComponent]
    });

    TestBed.overrideComponent(AppComponent, {
      set: {
        providers: [
          { provide: AppService, useClass: MockAppService }
        ]
      }
    });
  }));
  it('should render title in a h1 tag', async(() => {
    const fixture = TestBed.createComponent(AppComponent);
    fixture.detectChanges();
    const compiled = fixture.debugElement.nativeElement;
    expect(compiled.querySelector('h1').textContent).toContain('app works!');
  }));

Try this:

class MockAppService extends AbstractMockObservableService {
  getGuides() {
    return Observable.of([]);
  }
}

I just had this issue myself. In my case I was using a spy like this:

spy = spyOn(someService, 'get')
    .and.returnValue([]);

What I needed to do was do this:

spy = spyOn(someService, 'get')
    .and.returnValue(Observable.of([]));

There is no takeUntil method for your mock implementation because it's not returning an observable (unlike the real implementation).

getGuides()在你的MockAppService不应该返回this ,但可观察到的。

您需要在spec文件中导入它:

import 'rxjs/add/operator/takeUntil';

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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