在Angular 4单元测试中没有调用ngOnChanges detectChanges()

时间:2018-01-03 22:31:24

标签: angular unit-testing promise angular-components angular-unit-test

问题

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

我的代码

我的按钮组件有一个承诺

的输入
  /**
   * 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);
}

然后我存储一系列活跃的promises,以便在

中传递多个promises
  /**
   * 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);
    });
  }

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

[disabled]="activityPromises.length > 0"

帮助我obi-wan

我一直在尝试使用不同的东西来完成这项工作,这是我目前的测试代码,它不起作用。基本上我需要在promise解析之前检查按钮是否被禁用,然后我会想要进行另一个测试,检查它是否在promise解析后重新启用。

  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();
    });
  }));

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

2 个答案:

答案 0 :(得分:2)

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

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.

答案 1 :(得分:2)

这个问题的简短回答是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();

  }));