使用Jasmine测试基于HTTP的异步功能并等待:预期对标准"..."的一个匹配请求,未找到 [英] Testing async HTTP-based function with Jasmine and await: Expected one matching request for criteria "...", found none

查看:208
本文介绍了使用Jasmine测试基于HTTP的异步功能并等待:预期对标准"..."的一个匹配请求,未找到的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

内容:测试使用await的异步功能

WHAT: Testing an async function that uses await

与:Angular 9,茉莉花3.4.0

WITH: Angular 9, Jasmine 3.4.0

要复制的最小代码: StackBlitz

我有这样的功能.注意,它必须等待this.getHeaders().每当我删除await并将getHeaders()的实现替换为某些同步实现时,该测试就会成功运行.

I have a function like this. Note, that it has to await this.getHeaders(). Whenever I remove await and replace the implementation of getHeaders() by some synchonous implementation, the test runs successfully.

测试它的正确方法是什么?

What is the correct way to test it?

private async loadUserData() {
    // Try to remove await - the test runs successfully
    //const headers = this.getHeaders();
    const headers = await this.getHeaders();
    return this.httpClient
      .get<UserData>(window.location.origin + '/12345', { headers })
      .toPromise()
      .then((data) => {
        this.userData = data;
      })
      .catch((e) => {
        console.log('Oh noooo...');
      });
  }

我尝试过的事情:

  • 可能是StackBitz中的网址不正确,但 在本地测试时,我确定是的,因此这不应该成为根源 原因
  • 不确定,如果fakeAsync()是否有用-纯" http测试有效...
  • It might be the case that the url in StackBitz is not correct, but when testing locally I am sure it is, so this should not be the root cause
  • not sure, if fakeAsync() will help - the "pure" http test works...

不重复:

  • Not sure if timeout on flush would help in my case
  • I don't use any params on my url

推荐答案

您非常亲密.现在,您的测试已正确构建,但是您需要Angular提供的一些测试实用程序,以确保按正确的顺序解决了您的承诺,以使您的期望正确.

You're very close. Your test is now structured properly but you need some testing utilities provided by Angular to make sure that your Promises are resolved in the correct order for your expectations to be correct.

最终,该问题与角度区域有关.因为您要在服务中构造承诺,所以必须在发出传出请求之前进行承诺解析.您在测试中调用loadUserData,然后在下一行中写一个断言,指出确保此请求已发生,否则就不是错误".当您以不使用异步原语(例如PromiseObservable)的方式编写标头检索功能时,此请求立即"发生.但是,当您使用Promise时,不会立即"发生任何请求.相反,它必须首先解析您的标头检索功能.

Ultimately the problem relates to Angular zones. Because you're structuring promises in your service, and that promise resolution must occur before an outgoing request occurs. You call loadUserData in your test, and then on the next line you write an assertion that says "make sure that this request happened, if not that's an error". When you write your header retrieval function in such a way that you don't use an async primitive (like Promise or Observable) this request happens "immediately". But when you use a Promise, no request happens "immediately". Instead, it has to resolve your header retrieval function first.

幸运的是,您的测试失败只是测试环境的一个幻像功能,而不是实现中的错误.就像我说的,Angular为您提供了一些测试工具,以确保您可以在编写断言之前刷新"所有未完成的promise.

Luckily, your test failing is just a phantom feature of the test environment and not a bug in your implementation. Like I said, Angular gives you some testing tools to make sure you can "flush" all pending promises before writing an assertion.

import { fakeAsync,  tick } from '@angular/core/testing';

// instead of using `done`, which is just fine btw, we wrap our test function
// in fakeAsync(). This let's us have fine grained control over stepping through
// our code under test
it('should return user data on success', fakeAsync(() => {
  const mockUserData : UserData = {
    name: 'John',
      surname: 'Do',
      id: '12345'
    };

    (service as any).loadUserData().then(() => {
      expect((service as any).userData).toEqual(mockUserData);
      //expect(req.request.method).toEqual('GET');
    });

    // tick() steps through the next round of pending asynchronous activity
    // this will also step through 'setTimeout' and 'setInterval' code
    // you may have in your service, as well as Observable code
    tick();
    const req = httpTestingController.expectOne(
      'https://testing-qh48mg.stackblitz.io/12345',
    );
    req.flush(mockUserData);
}));

更新了 Stackblitz . fakeAsync 上的文档. 有关使用tick在Angular中测试Http代码的相关问题.

Updated Stackblitz. Docs on fakeAsync. Related question on testing Http code in Angular using tick.

这篇关于使用Jasmine测试基于HTTP的异步功能并等待:预期对标准"..."的一个匹配请求,未找到的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆