为什么 Jasmine expect().toHaveBeenCalled 断言在没有包装函数的情况下会失败

Why do Jasmine expect().toHaveBeenCalled assertions fail without wrapper function

如果我有这样的订阅

this.submit$.subscribe(this.handleSubmit);

我也是这样测试的

it('should set up a subscription on submit$', () => {
  spyOn(component, 'handleSubmit');
  component.submits$.next(data);
  expect(component.handleSubmit).toHaveBeenCalledTimes(1);
  expect(component.handleSubmit).toHaveBeenCalledWith(data);
});

我收到这个错误:

Error: Expected spy handleSubmit to have been called once. It was called 0 times.

如果我为订阅回调创建一个新的匿名函数,一切正常:

this.submit$.subscribe(data => this.handleSubmit(data));

为什么我需要创建这个额外的函数才能通过测试?

this.submit$.subscribe(this.handleSubmit) 在构造函数中。当我在测试中调用 spyOn(component, 'handleSubmit') 时,已经调用了构造函数并且已经创建了订阅。即使我现在在 handleSubmit 上有一个间谍,订阅总是会调用原始的 handleSubmit

当使用匿名函数作为订阅回调时 this.submit$.subscribe(data => this.handleSubmit(data)) 订阅与该匿名函数相关联。这使我能够在调用 handleSubmit 之前监视它,因为匿名函数在 submit$ 发出之前不会被调用。

我通过将 this.submit$.subscribe(this.handleSubmit); 移动到 ngOnInit 来解决这个问题,这样我就可以控制何时创建订阅。