以角度测试基于Observable的调用层次结构

时间:2017-04-30 12:17:42

标签: unit-testing angular typescript jasmine

我正在尝试测试一个使用Observables的组件,然后在Observable解析时级联几个函数调用。这是组件的一个版本。

export class NotificationComponent implements OnInit {
  private answerSubscription: Subscription;

  constructor(public toasterService: ToasterService, private commentService: CommentService) { }

  ngOnInit() {
    this.answerSubscription = this.commentService.answer$.subscribe(
      answer => this.commentComplete(answer));
  }

  commentComplete(answer) {
    this.toasterService.clear(answer.toastId);
    let promptAns = this.search(answer.toastId);
  }    
}

这是我的测试:

class MockToastService {
  clear() {}
 }
class MockCommentService {
  answer$: Observable<any>;
  constructor() {
    this.answer$ = Observable.of({toastId: '123'});
  }
}
describe('NotificationComponent', () => {
  let component: NotificationComponent; let fixture: ComponentFixture<NotificationComponent>;
  let mockComment = new MockCommentService(); let mockToast = new MockToastService();

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [NotificationComponent, MockToast],
      providers: [{ provide: ToasterService, useValue: mockToast },
                  { provide: CommentService, useValue: mockComment }]
    }).compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(NotificationComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('should complete notification on answer', () => {
    spyOn(component, 'commentComplete'); spyOn(mockToast, 'clear');
    expect(component.commentComplete).not.toHaveBeenCalled();
    component.ngOnInit();
    expect(component.commentComplete).toHaveBeenCalled();
    expect(mockToast.clear).toHaveBeenCalled();
  });
});

测试在expect(component.commentComplete).toHaveBeenCalled();上传递,但在expect(mockToast.clear).toHaveBeenCalled()上失败。从组件中可以看出,toasterService.clear(应该在commentComplete之后直接调用,但是,我已经使用调试器,并且在调用clear函数之前正在检查测试条件。

我尝试添加fakeAsynctick(),但我仍然面临着这个问题。知道如何让这个测试的计时工作吗?

1 个答案:

答案 0 :(得分:1)

你应该在这里使用假的异步,但是要理解那里没有问题。

你通过spyOn(组件,'commentComplete')伪造'commentComplete'函数,但你需要间谍并完成它的工作。改为'spyOn(component,'commentComplete')。and.callThrough();'

  

Spies:and.callThrough。通过使用and.callThrough链接间谍,间谍仍将跟踪对它的所有调用,但此外它将委托给实际的实现。

savez

这是应该有效的代码:

it('should complete notification on answer', fakeAsync(() => {
  const spyComplete = spyOn(component, 'commentComplete').and.callThrough();
  const spyToast = spyOn(mockToast, 'clear');

  expect(component.commentComplete).not.toHaveBeenCalled();
  component.ngOnInit();

  tick();

  expect(spyComplete).toHaveBeenCalled();
  expect(spyToast).toHaveBeenCalled();
}));