1

I have some Components and Services that perform operations periodically in the background -- refreshing data, updating the displayed date/time, etc. I originally wrote these features using setInterval. Now, I'm going back to add unit tests. I spent way too long trying to figure out why my tests weren't working -- turns out that fixture.whenStable() will never resolve if the component under test (or any of its dependencies!) create an interval. I tried switching from setInterval to rxjs interval / timer, but those have the same problem.

The advice given on this older question is to put actual setInterval calls inside a dedicated "interval service", then mock out the service with something tick-able when writing tests. I don't love the idea of changing my (working!) code to accommodate testing, if I can help it, but I think I really need whenStable to work. Among other things, the Angular Material TestbedHarnessEnvironment uses it under the hood, so as far as I can tell, any component that includes an interval can't use Material harnesses.

My question is: as of late 2020, do I have any better options? Is there a way to write waitForAsync-style tests for Components or Services that include an actual interval? Or is there a better pattern I can use for my Component design, maybe some interval replacement that's integrated with existing Zone.js testing patches?

Coderer
  • 25,844
  • 28
  • 99
  • 154

1 Answers1

0

I had a similar (not identical) problem, which I solved as follows: in the test code, right after invoking fixture.detectChanges(), I stopped my timers (by unsubscribing). The only change in the tested code is to expose the unsubscribe code with a public function, for example:

stopTimers() {
  this.intervalSubs?.unsubscribe();
}

Then in your test code:

component = fixture.componentInstance;
fixture.detectChanges();
component.stopTimers();
Reuben Sivan
  • 157
  • 9
  • I had forgotten about this question. I never did come up with a better solution. In some cases, I was able to use `whenStable` by mocking out a dependency on a service that uses timers (of course the mock doesn't need them), and in others I just avoided `whenStable` and relied on manually `tick`-ing, with a `discardPeriodicTasks` at the end of a test. I never did adopt `TestbedHarnessEnvironment`... – Coderer May 20 '21 at 09:37