【问题标题】:ngOnChanges not called in Angular 4 unit test detectChanges()Angular 4 单元测试中未调用 ngOnChanges detectChanges()
【发布时间】:2018-06-13 15:27:51
【问题描述】:

问题

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

我的代码

我的按钮组件有一个承诺的输入

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

然后我存储了一个活跃的 promise 数组,因此可以传入多个 promise

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

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

【问题讨论】:

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


    【解决方案1】:

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

    【讨论】:

      【解决方案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);
      }));
      

      编辑: 如 cmets 所述,您设置 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.
      

      【讨论】:

      • 嘿!谢谢你的建议。不幸的是,这给了我“预期错误为真的”。 for "expect(buttonElement.disabled).toBe(true);"
      • 这是由于您的组件的工作方式,可能是一个单独的问题。我在这里手动添加了对ngOnChanges() 的调用(当您像这样直接更改属性时,TestBed 不会调用 ngOnChanges),或者更好的解决方案是将组件包装在主机组件中。
      猜你喜欢
      • 2023-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-16
      相关资源
      最近更新 更多