在继续

时间:2017-04-13 20:35:52

标签: angular asynchronous jasmine angular2-testing

在我的代码中,我有一个返回零件对象的方法,但它返回setTimeout方法内的对象。当我尝试测试这个时,我遇到的问题是测试不会等到超时完成后再评估方法的响应。如何在检查期望之前告诉测试等待超时完成?

正如您所看到的,getIntersection方法在超时内返回this.part。

public getIntersection(payload: DropPayload): Part {
  let rect: ClientRect = this.element.nativeElement.getBoundingClientRect();
  if (rect.left < payload.event.pageX && rect.right > payload.event.pageX && rect.top < payload.event.pageY && rect.bottom > payload.event.pageY) {
    setTimeout(() => {
      this.changeRef.detectChanges();
      return this.part;
    });
  }
  return null;
}

以下是我在研究此问题时尝试过的一些事情,但这些事情都没有效果:

1:

it('return the part if the payload coordinates are inside the bounding box', async((done) => {
  partInstance.part = Clone.create(mockPart);
  let result: any = partInstance.getIntersection(mockPayload);
  setTimeout(() => {
    expect(result).toEqual(mockPart);
    done();
  });
}));

2:

it('return the part if the payload coordinates are inside the bounding box', async(() => {
  partInstance.part = Clone.create(mockPart);
  let result: any = partInstance.getIntersection(mockPayload);
  setTimeout(() => {
    expect(result).toEqual(mockPart);
  });
}));

3 :(这个引发了runs未定义的错误。我相信这是一个Angular 1解决方案)

it('return the part if the payload coordinates are inside the bounding box', () => {
  let done: boolean = false;
  let result: any;
  runs(() => {
    partInstance.part = Clone.create(mockPart);
    result = partInstance.getIntersection(mockPayload);
    setTimeout(() => {
      done = true;
    });
  });
  waitsFor(() => {
    return done;
  });
  runs(() => {
      expect(result).toEqual(mockPart);
  });
});

4:

it('return the part if the payload coordinates are inside the bounding box', () => {
  partInstance.part = Clone.create(mockPart);
  let result: any = partInstance.getIntersection(mockPayload);
  setTimeout(() => {
    expect(result).toEqual(mockPart);
  });
});

1 个答案:

答案 0 :(得分:0)

看看你的逻辑

public getIntersection(payload: DropPayload): Part {
  let rect: ClientRect = this.element.nativeElement.getBoundingClientRect();
  if (rect.left < payload.event.pageX && rect.right > payload.event.pageX && rect.top < payload.event.pageY && rect.bottom > payload.event.pageY) {
    setTimeout(() => {
      this.changeRef.detectChanges();
      return this.part;
    });
  }
  return null;
}

两件事:

  1. setTimeout异步发生。但主函数的返回同步发生。返回值始终为null

  2. setTimeout的回调中返回不符合你的想法,即神奇地使返回值成为别的东西。你在回调中返回的内容不是主函数的返回值是什么。

  3. 您需要重新构建代码,也许需要使用promises。让方法返回一个承诺

    public getIntersection(payload: DropPayload): Promise<Part> {
      let rect: ClientRect = this.element.nativeElement.getBoundingClientRect();
    
      return new Promise((resolve) => {
        setTimeout(() => {
          this.changeRef.detectChanges();
          resolve(this.part);
        })
      })
    }
    

    我不知道你的方法背后的逻辑是什么,所以我把它留了出来。但是你可能需要以某种方式将它合并。

    然后你可以调用像

    这样的函数
    getIntersection().then(part => {
      expect(...)
    })
    

    使用Angular async的尝试应该适用于此。