使用Jamine测试基于HTTP的异步功能:超时-在5000毫秒内未调用异步回调

时间:2020-05-19 18:23:38

标签: angular promise callback jasmine karma-jasmine

内容:测试异步函数以返回依赖于嵌套http调用的Promise

与:Angular 9,茉莉花3.4.0

问题:错误:超时-在5000毫秒(由jasmine.DEFAULT_TIMEOUT_INTERVAL设置)内未调用异步回调 错误:未找到打开的请求,发现1:GET http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909

import ...

export interface UserData {...}

@Injectable()
export class UserDataManagementService {
  private userID: string | undefined;
  public userData: UserData;

  constructor(...) {}

  private async loadUserData() {
    const headers = await this.getHeaders();
    return this.httpClient
      .get<UserData>(window.location.origin + '/' + this.userID, { headers })
      .toPromise()
      .then((data) => {
         this.userData = data;
      })
      .catch((e) => {
        this.logger.error('Error in loadUserData: ', e);
      });
  }

  private async getHeaders() {...}
}

这是我的考试:

import ...
const mockUserData: UserData = {...};

describe('UserDataManagementService', () => {
  let httpTestingController: HttpTestingController;
  let service: UserDataManagementService;
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        UserDataManagementService,
        ...
      ],
    });
    httpTestingController = TestBed.get(HttpTestingController);
    service = TestBed.get(UserDataManagementService);
 });

  afterEach(() => {
    httpTestingController.verify();
  });


describe('loadUserData', () => {
    it('should return user data on success', (done) => {
      (service as any).userID = '24a27be6-9f62-4156-8fd4-adcd945ec909';
      (service as any).loadUserData().then(() => {
        expect((service as any).userData).toEqual(mockUserData);
        const req = httpTestingController.expectOne( 
          'http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909',
        );
        expect(req.request.method).toEqual('GET');
        req.flush(mockUserData);
        done();
      });
    });
  });
});

我尝试过的很远:

  • 试图将默认超时时间增加到20000ms-不起作用
  • done / async / await等的不同组合。
  • httpTestingController.expectOne在then()之外的位置(虽然没有任何意义,但是我已经尝试了一切)
  • 如果我将httpTestingController.verify()放入此测试中,则错误“预期没有打开的请求...”消失

这不是以下内容的重复:

  • 我的函数返回一个承诺,例如here
  • 我使用done(),例如here
  • 我没有像here这样的长期任务
  • fakeAsync也不帮助我...

1 个答案:

答案 0 :(得分:1)

尽管我无法重现您的测试环境,但由于从未满足您的模拟请求,因此您的测试似乎正在超时。它从未实现的原因是因为您在旨在处理响应的回调中刷新了测试请求。

(service as any).loadUserData().then(() => {
        const req = httpTestingController.expectOne(
          'http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909',
        );
        expect((service as any).userData).toEqual(mockUserData);
        expect(getHeadersSpy).toHaveBeenCalled();
        expect(req.request.method).toEqual('GET');
        // this line tells the test scaffolding to fulfill the request
        req.flush(mockUserData); 
        done();
      });

我希望,如果您重构刷新请求,那么您的测试将不会超时(由于其他原因可能仍然失败)。

const req = httpTestingController.expectOne('http://localhost:9876/24a27be6-9f62-4156-8fd4-adcd945ec909');
(service as any).loadUserData().then(() => {
    expect((service as any).userData).toEqual(mockUserData);
    expect(getHeadersSpy).toHaveBeenCalled();
    expect(req.request.method).toEqual('GET');
    done();
});

req.flush(mockUserData); // <= essentially: 'call my callback now!'