Skip to content

testing: async test fails if SUT calls an observable with a delay operator (fakeAsync too) #10127

Closed
@wardbell

Description

@wardbell

I'm submitting a ... (check one with "x")

[x] bug report
[ ] feature request
[ ] support request 

Consider these two tests:

afterEach(() => { expect(actuallyDone).toEqual(true); });

// Async
it('should run async test with successful delayed Observable', async(() => {
  let actuallyDone = false;
  let source = Observable.of(true).delay(10);
  source.subscribe(
    val => {
      actuallyDone = true;
    },
    err => fail(err)
  );
}));

// FakeAsync
it('should run async test with successful delayed Observable', fakeAsync(() => {
  let source = Observable.of(true).delay(10);
  source.subscribe(
    val => {
      actuallyDone = true;
    },
    err => fail(err)
  );
  tick();
}));

Current behavior

Test 1 fails with message: Cannot use setInterval from within an async zone test
Test 2 fails with message: Error: 1 periodic timer(s) still in the queue.

In neither test does the actuallyDone value become true;

Expected/desired behavior

The test should not fail.

Reproduction of the problem

See above.

What is the expected behavior?

The test should not fail. We should allow async tests of stuff that calls setInterval. If we can't, we had better offer a message that helps the developer find likely sources of the problem (e.g, Observables).

What is the motivation / use case for changing the behavior?

I have no idea how to test a SUT with an Observable.delay() ... or any observable operator that calls setInterval.

Maybe I'm just using fakeAsync incorrectly. I'd like to know what to do.

Let's say we get that to work. Is that a solution?

I don't think so. It is generally impractical for me, the test author, to anticipate whether fakeAsync is necessary. I don't always know if the SUT (or something it uses ... like a service) makes use of setInterval.

Moreover, a test that was working could suddenly fail simple because someone somewhere modified the observable with an operator that calls setInterval. How would I know?

The message itself requires knowledge of which observables rely upon setInterval. I only guessed that delay did; it's not obvious that it should.

Please tell us about your environment:

  • Angular version: 2.0.0-rc.5 (candidate - 16 July 2016)
  • Browser: [ Chrome ]
  • Language: [TypeScript 1.8.x ]

Metadata

Metadata

Assignees

Labels

area: testingIssues related to Angular testing features, such as TestBed

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions