Angular 4 单元测试 detectChanges() 中未调用 ngOnChanges

ngOnChanges not called in Angular 4 unit test detectChanges()

问题

我有一个按钮组件,它接受承诺并禁用按钮,直到承诺已解决,我想为此功能编写单元测试。

我的代码

我的按钮组件有 promise 的输入

  /**
   * A single promise that triggers the busy state until it resolves
   */
  @Input()
  public promise: Promise<any>;

在 ngOnChanges 中,我倾听承诺

/**
 * Enable button busy state until promise resolves
 */
if (changes && changes.promise && changes.promise.currentValue) {
  this.busyUntilPromiseResolves(changes.promise.currentValue);
}

然后我存储一组活动承诺,以便可以传入多个承诺

  /**
   * Add a promise that will keep the button in a busy state until it resolves
   * @param activityProimise
   */
  private busyUntilPromiseResolves(activityProimise) {
    this.activityPromises.push(activityProimise);
    activityProimise.then(() => {
      this.activityPromises.splice(this.activityPromises.indexOf(activityProimise), 1);
    });
  }

最后在我的模板中,如果数组中有任何承诺,我会禁用按钮。

[disabled]="activityPromises.length > 0"

欧比旺帮帮我

我一直在尝试不同的方法来完成这项工作,这是我当前的测试代码,但它不起作用。基本上我需要在承诺解决之前检查按钮是否被禁用,然后我想做另一个测试来检查它在承诺解决后重新启用。

  it('should be disabled when passed a single promise', async((done) => {
    let promise;

    return promise = new Promise(resolve => {
      component.promise = promise;
      fixture.detectChanges();
      expect(buttonElement.disabled).toBe(true);
      return resolve();
    });
  }));

一如既往,我们将不胜感激,谢谢。

您是否尝试过在添加该承诺之前断言?

it('should be disabled when passed a single promise', async(() => {
  let promise;
  // should not be disabledhere
  expect(buttonElement.disabled).toBe(false);
  let resolve;
  const promise = new Promise(r => resolve = r);
  component.promise = promise;
  component.ngOnChanges(); // Call this here, TestBed doesn't know it needs to.
  fixture.detectChanges();
  expect(buttonElement.disabled).toBe(true);

  // now resolve the promise and make sure it's disabled again.
  resolve();
  fixture.detectChanges();
  expect(buttonElement.disabled).toBe(false);
}));

编辑: 如评论中所述,您设置 promise 属性 的方式不适用于 TestBed,因此它永远不会调用您的ngOnChanges() 方法。你可以直接调用它,就像我上面那样。

或者,将您的测试组件包装在主机组件中:

@Component({
  selector: 'test-component',
  template: `<my-component [promise]="promise"></my-component>`
})
class TestComponent {
  promise;
}

// then use that in your test instead:
const wrapperCmp = TestBed.createComponent(TestComponent);
wrapperCmp.promise = promise; // and check for the button state before and after all the changes.

这个问题的简短回答是 ngOnChanges 在单元测试期间不会自动触发,所以我不得不手动调用它。

it('should be disabled when passed a single promise', async () => {
    let promise;
    let resolve;

    // should not be disabled here
    expect(buttonElement.disabled).toBe(false);

    // Pass a promise to the component to disable it
    promise = new Promise((r) => (resolve = r));
    component.ngOnChanges({
        promise: new SimpleChange(null, promise, null),
    });

    fixture.detectChanges();
    expect(buttonElement.disabled).toBe(true);

    // now resolve the promise and make sure it's enabled again.
    promise.then(() => {
        fixture.detectChanges();
        expect(buttonElement.disabled).toBe(false);
    });

    resolve();
});