簡體   English   中英

用 Jasmine 監視 Observable 訂閱的結果

[英]Spy on the result of an Observable Subscription with Jasmine

我是 Jasmine 單元測試一個使用 Observables 的角度組件。 我的組件有我正在測試的這個生命周期鈎子:

ngOnInit() {
  this.dataService.getCellOEE(this.cell).subscribe(value => this.updateChart(value));
}

我有一個測試來確保 getCellOEE 已被調用,但現在我想檢查當 observable 使用新值解析時是否調用了 updateChart。 這是我到目前為止:

let fakeCellService = {
  getCellOEE: function (value): Observable<Array<IOee>> {
    return Observable.of([{ time: moment(), val: 67 }, { time: moment(), val: 78 }]);
  }
};

describe('Oee24Component', () => {
  let component: Oee24Component;
  let service: CellService;
  let injector: Injector;
  let fixture: ComponentFixture<Oee24Component>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [Oee24Component],
      providers: [{ provide: CellService, useValue: fakeCellService }]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(Oee24Component);
    component = fixture.componentInstance;
    injector = getTestBed();
    service = injector.get(CellService)
    fixture.detectChanges();
    spyOn(service, 'getCellOEE').and.returnValue({ subscribe: () => { } });
    spyOn(component, 'updateChart');
  });

  it('should get cell oee on init', () => {
    component.ngOnInit();
    expect(service.getCellOEE).toHaveBeenCalled();
  });

  it('should update chart on new data', () => {
    component.ngOnInit();
    expect(component.updateChart).toHaveBeenCalled();
  });
});

但是,我收到錯誤:

chrome 56.0.2924 (Windows 10 0.0.0) Oee24Component 應該更新新數據圖表失敗

預期間諜 updateChart 已被調用。

大概這是一個時間問題,因為當測試檢查時,observable 不一定解決? 如果是這種情況,我該如何正確設置?

更新:

這是我的組件:

@Component({
  selector: 'app-oee24',
  templateUrl: './oee24.component.html',
  styleUrls: ['./oee24.component.css']
})
export class Oee24Component implements OnInit {
  public barChartData: any[] = [{ data: [], label: 'OEE' }];

  constructor(public dataService: CellService) { }

  ngOnInit() {
    this.dataService.getCellOEE(this.cell).subscribe(value => this.updateChart(value));
  }

  updateChart(data: Array<IOee>) {
    this.barChartData[0].data = data.map(val => val.val);
  }
}
 

你有沒有想過解決辦法? 使用jasmine-marbles包和complete事件怎么樣?

it('should update chart on new data', () => {
    const obs$ = cold('--a-|');
    spyOn(service, 'getCellOEE').and.returnValue(obs$);
    component.ngOnInit(); 
    obs$.subscribe({
        complete: () => {
            expect(component.updateChart).toHaveBeenCalledWith('a');
        }
    });
});

不確定這是否是最好的方法,但我已經看到它在我正在從事的項目中工作。 該方法基本上是獲取對提供給 subscribe 方法的回調函數的引用,並手動調用它以模擬觀察者發出值:

it('should update chart on new data', () => {
    component.ngOnInit();

    // this is your mocked observable
    const obsObject = service.getCellOEE.calls.mostRecent().returnValue;

    // expect(obsObject.subscribe).toHaveBeenCalled() should pass

    // get the subscribe callback function you provided in your component code
    const subscribeCb = obsObject.subscribe.calls.mostRecent().args[0];

    // now manually call that callback, you can provide an argument here to mock the "value" returned by the service
    subscribeCb(); 

    expect(component.updateChart).toHaveBeenCalled();
  });

代替

spyOn(service, 'getCellOEE').and.returnValue({ subscribe: () => { } });

你可以試試

spyOn(service, 'getCellOEE').and.returnValue( {subscribe: (callback) => callback()});

fixture.detectChanges觸發器ngOnInit 所以,沒有必要要求ngOnInit如果手動fixture.detectChanges被執行。

檢查方法是否被調用是一種不好的做法。 相反,檢查代碼執行的預期結果更可靠。

spyOn(service, 'getCellOEE').and.returnValue({ subscribe: () => { } });行中spyOn(service, 'getCellOEE').and.returnValue({ subscribe: () => { } }); 因為fakeCellService已經正確地fakeCellService了該服務。

測試的代碼是異步的,所以我們需要等到它被執行。 await fixture.whenStable(); 正是這樣做的。

所以,結果測試:

const fakeData = [{ time: moment(), val: 67 }, { time: moment(), val: 78 }];
const expectedChartData = [67, 78];
const fakeCellService = {
  getCellOEE: function (value): Observable<Array<IOee>> {
    return Observable.of(fakeData);
  }
};

describe('Oee24Component', () => {
  let component: Oee24Component;
  let service: CellService;
  let injector: Injector;
  let fixture: ComponentFixture<Oee24Component>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [Oee24Component],
      providers: [{ provide: CellService, useValue: fakeCellService }]
    })
      .compileComponents();
  }));

  beforeEach(async () => {
    fixture = TestBed.createComponent(Oee24Component);
    component = fixture.componentInstance;
    fixture.detectChanges();
    await fixture.whenStable();
  });

  it('maps and saves value from the CellService.getCellOEE to barChartData[0].data when initialized', () => {
    expect(component.barChartData[0].data).toEqual(expectedChartData);
  });
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM