为啥 TestBed beforeeach 使用 waitForAsync 而不仅仅是 async/await compileComponents?

Posted

技术标签:

【中文标题】为啥 TestBed beforeeach 使用 waitForAsync 而不仅仅是 async/await compileComponents?【英文标题】:Why TestBed beforeeach uses waitForAsync instead of just async/await compileComponents?为什么 TestBed beforeeach 使用 waitForAsync 而不仅仅是 async/await compileComponents? 【发布时间】:2021-03-01 21:17:42 【问题描述】:

编辑:我在 Angular 上打开了一个问题,他们更新了文档:https://github.com/angular/angular/issues/39740

在 Angular 测试中,通常的做法是为 beforeEach 方法执行此操作

    beforeEach(waitForAsync(() => 
      TestBed
          .configureTestingModule(
            declarations: [BannerComponent],
          )
          .compileComponents();  // compile template and css
    ));

跟下面做有什么区别?

    beforeEach(async () => 
      await TestBed
          .configureTestingModule(
              declarations: [BannerComponent],
          )
          .compileComponents();  // compile template and css
    );

我试图在文档中找到解释,但无法弄清楚。

https://angular.io/api/core/testing/waitForAsync#description https://v10.angular.io/guide/testing-components-scenarios#the-async-beforeeach

【问题讨论】:

【参考方案1】:

关于这两种方法

我们有多种方法可以在测试角度操作时定义异步操作

使用waitForAsync()

waitForAsync

在异步测试区域中包装测试函数。当该区域内的所有异步调用都完成后,测试将自动完成。可用于包装注入调用。 来自文档

另外需要注意的是,这个方法是对初始方法async的重命名。

async

已弃用:使用 waitForAsync(),(预计在 v12 中删除)

async() 助手重命名

测试帮助函数async 已被弃用并重命名为waitForAsync

这个重命名背后的原因是,当我们现在有一个名为 asyncjavascript 关键字(创建 Angular 函数时该关键字不存在)时,有一个名为 async() 的函数可能会令人困惑,这有点类似(您可以await 异步调用),但不同(async() 等待所有异步调用,其中async 只等待标记为 await 的调用)。

归功于Cédric ExbrayatSee this article

WaitForAsync 函数在一个特殊的异步测试区执行其主体内的代码。这会跟踪在正文中创建的所有承诺。该函数还跟踪由嵌套函数创建的任何承诺,例如,如果我们在 ngOnInit 函数中调用异步函数,这将被跟踪。

使用Async/ Await

基本上这使用普通的 Javascript async\ await。我们将一个函数声明为 async 并等待一个 Promise 解决

这两种方法有什么区别?

让我们考虑一个有 5 种方法的测试asyncMethod1,nonAsyncMethod1,asyncMethod2,asyncMethod3,nonAsyncMethod2

使用async / await。我们需要在下面做

beforeEach(async () => 
   await asyncMethod1();
   nonAsyncMethod1(); 
   await asyncMethod2();
   await asyncMethod3();
   nonAsyncMethod2()
   await TestBed
      .configureTestingModule(
          declarations: [BannerComponent],
      )
      .compileComponents();  // compile template and css
);

使用waitForAsync 以上将是

beforeEach(waitForAsync(() => 
   asyncMethod1();
   nonAsyncMethod1(); 
   asyncMethod2();
   asyncMethod3();
   nonAsyncMethod2()
   TestBed
      .configureTestingModule(
        declarations: [BannerComponent],
      )
      .compileComponents();  // compile template and css
));

所以通常在使用async /await 时,我们需要在使用waitForAsync 时跟踪我们所有的异步操作,这将由函数跟踪,并且一旦函数主体中的所有承诺都得到解决,承诺就会解决

【讨论】:

所以我的两个sn-ps没有区别。 两个 sn-ps 的功能完全相同,但我建议使用 waitForAsync 好吧,这很奇怪,因为 Angular 11 CLI 使用 async/await 而不是 waitForAsync 生成一个测试文件 这里我是使用 async 作为 JS 操作,这不是 Angular 重构的 async 函数 这里只是说Angular 12为组件生成的规范文件默认使用async/await而不是waitForAsync

以上是关于为啥 TestBed beforeeach 使用 waitForAsync 而不仅仅是 async/await compileComponents?的主要内容,如果未能解决你的问题,请参考以下文章

Angular 2 测试 - 异步函数调用 - 何时使用

为啥在 V8Js 中运行时,Vue 路由器 beforeEach 中的错误不会抛出异常?

Angular单元测试没有通过 - 异常的phantomjs错误

Angular 7 TestBed.overrideProvider 不适用于 ActivateRoute

Angular 2:如何在单元测试时模拟 ChangeDetectorRef

Angular 4 单元测试(TestBed)非常慢