angular / angular/components

bug(TestbedHarnessEnvironment): Impossible to use if component under test uses intervals

Offen
#20,785 5 Kommentare 0 Reaktionen 0 zugewiesene Personen Auf GitHub ansehen
area: cdk/testing P3
Vorherrschende Sprache
TypeScript
Sterne
25k
Forks
6.8k
Ø Merge
1 T. 8 Std.
Gemergte PRs (30 T.)
91

Beschreibung

Use StackBlitz to reproduce your issue: **ADDED** (thanks @annieyw!), [example here](https://stackblitz.com/edit/material-testbedharness-interval?file=src/app/button-harness-example.spec.ts)

Steps to reproduce:
1. Follow [the instructions for using Harnesses](https://material.angular.io/guide/using-component-harnesses)
2. In the component under test, use `setInterval`, or the rxjs `interval(n)` or `timer(0, n)` observables
3. Your test will stall indefinitely at e.g. `await loader.getAllHarnesses(MatButtonHarness);` (from the docs linked in step 1)

#### Expected Behavior

`getAllHarnesses` completes once the component has finished initializing and had a chance to create instances of child components.

#### Actual Behavior

The call to `getAllHarnesses` never resolves, and the test times out.

#### Environment

- Angular: 10.1.2
- CDK/Material: 10.2.1
- Browser(s): N/A
- Operating System (e.g. Windows, macOS, Ubuntu): N/A (Win10)

----

As I understand it, this is because under the hood, `TestbedHarnessEnvironment` is using `ComponentFixture#whenStable`. From what I can tell, [the official stance from Angular / Zone](https://github.com/angular/angular/issues/10127) is that you should use `fakeAsync` plus `tick`, and call `discardPeriodicTasks` to ignore the (expected) pending intervals, instead of using `waitForAsync` / `whenStable`.

This [very old StackOverflow question](https://stackoverflow.com/questions/38697656/testing-angular2-components-that-use-setinterval-or-settimeout) suggests that one should never have `setInterval` in a component or service, instead using an injected service to provide periodic actions, so it can be mocked out during testing, but I've never seen anything "official" from Angular to say that intervals are unsupported.

If it's not permissible to use intervals in a component, this should be documented somewhere, with suggestions of alternative design patterns to use that are compatible with Material's test utilities. If it is permissible, `TestbedHarnessEnvironment` should be updated to include another way of determining when the owning `ComponentFixture` is "ready", or I guess kick this upstream to the Zone folks so they can make `whenStable` work with intervals.

Beitragsleitfaden

Beitragsleitfaden öffnen

Rechercherichtung

Beginne mit der StackBlitz-Reproduktion und dem Einstiegspunkt TestbedHarnessEnvironment und konzentriere dich auf dessen Verwendung von ComponentFixture#whenStable. Vergleiche das Verhalten mit den verlinkten Angular- und Zone-Anleitungen zu fakeAsync, tick und discardPeriodicTasks. Erledigt ist die Aufgabe, wenn für den Intervallfall ein vereinbartes unterstütztes Verhalten feststeht, entweder ein funktionierender Harness-Pfad oder eine Dokumentation, die die Einschränkung und das kompatible Testmuster erklärt.

Vom Indexierungsmodell aus dem Issue-Text verfasst.

Bewertung

Tech-Stack
angular, typescript
Bereich
testing
Issue-Typ
Bug
Schwierigkeit
5/5
Geschätzter Aufwand
Über eine Woche
Aktivitätsstatus
Veraltet
Klarheit
Größtenteils klar
Anfängerfreundlichkeit
25/100

Neue Issues direkt in Ihr Postfach

Eine kurze Übersicht über anfängerfreundliche GitHub-Issues.