docs(testing): incorporate Igor Minar feedback, Part 2 (#2453)
docs(testing): incorporate Igor Minar feedback, Part 2
This commit is contained in:
parent
f45c9998cc
commit
3ee19780b5
|
@ -706,15 +706,14 @@ a(href="#top").to-top Back to top
|
||||||
:marked
|
:marked
|
||||||
### Synchronous tests
|
### Synchronous tests
|
||||||
The first two tests are synchronous.
|
The first two tests are synchronous.
|
||||||
Neither test can prove that a value from the service will be displayed.
|
Thanks to the spy, they verify that `getQuote` is called _after_
|
||||||
|
the first change detection cycle during which Angular calls `ngOnInit`.
|
||||||
Thanks to the spy, the second test verifies that `getQuote` is called.
|
|
||||||
But the quote itself has not arrived, despite the fact that the spy returns a resolved promise.
|
|
||||||
|
|
||||||
This test must wait at least one full turn of the JavaScript engine, a least one "tick", before the
|
|
||||||
value becomes available. By that time, the test runner has moved on to the next test in the suite.
|
|
||||||
|
|
||||||
The test must become an "async test" ... like the third test
|
Neither test can prove that a value from the service is be displayed.
|
||||||
|
The quote itself has not arrived, despite the fact that the spy returns a resolved promise.
|
||||||
|
|
||||||
|
This test must wait at least one full turn of the JavaScript engine before the
|
||||||
|
value becomes available. The test must become _asynchronous_.
|
||||||
|
|
||||||
#async
|
#async
|
||||||
:marked
|
:marked
|
||||||
|
@ -724,10 +723,9 @@ a(href="#top").to-top Back to top
|
||||||
+makeExample('testing/ts/app/shared/twain.component.spec.ts', 'async-test', 'app/shared/twain.component.spec.ts (async test)')(format='.')
|
+makeExample('testing/ts/app/shared/twain.component.spec.ts', 'async-test', 'app/shared/twain.component.spec.ts (async test)')(format='.')
|
||||||
:marked
|
:marked
|
||||||
The `async` function is one of the Angular testing utilities.
|
The `async` function is one of the Angular testing utilities.
|
||||||
|
It simplifies coding of asynchronous tests by arranging for the tester's code to run in a special _async test zone_.
|
||||||
|
|
||||||
It simplifyies coding of asynchronous tests by arranging for the tester's code to run in a special _async test zone_.
|
The `async` function _takes_ a parameterless function and _returns_ a function
|
||||||
|
|
||||||
The `async` function _takes_ a parameterless function and _returns_ a parameterless function
|
|
||||||
which becomes the argument to the Jasmine `it` call.
|
which becomes the argument to the Jasmine `it` call.
|
||||||
|
|
||||||
The body of the `async` argument looks much like the body of a normal `it` argument.
|
The body of the `async` argument looks much like the body of a normal `it` argument.
|
||||||
|
@ -736,17 +734,14 @@ a(href="#top").to-top Back to top
|
||||||
there is no `done` function to call as there is in standard Jasmine asynchronous tests.
|
there is no `done` function to call as there is in standard Jasmine asynchronous tests.
|
||||||
|
|
||||||
Some functions called within a test (such as `fixture.whenStable`) continue to reveal their asynchronous behavior.
|
Some functions called within a test (such as `fixture.whenStable`) continue to reveal their asynchronous behavior.
|
||||||
Consider also the [_fakeAsync_](#fake-async) alternative which affords a more linear coding experience.
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
The `fakeAsync` alternative, [covered below](#fake-async), removes this artifact and affords a more linear coding experience.
|
||||||
|
|
||||||
#when-stable
|
#when-stable
|
||||||
:marked
|
:marked
|
||||||
## _whenStable_
|
## _whenStable_
|
||||||
The test must wait for the `getQuote` promise to resolve.
|
The test must wait for the `getQuote` promise to resolve in the next turn of the JavaScript engine.
|
||||||
|
|
||||||
The `getQuote` promise promise resolves in the next turn of the JavaScript engine, thanks to the spy.
|
|
||||||
But a different test implementation of `getQuote` could take longer.
|
|
||||||
An integration test might call the _real_ `getQuote`, resulting in an XHR request
|
|
||||||
that took many seconds to respond.
|
|
||||||
|
|
||||||
This test has no direct access to the promise returned by the call to `testService.getQuote`
|
This test has no direct access to the promise returned by the call to `testService.getQuote`
|
||||||
which is private and inaccessible inside `TwainComponent`.
|
which is private and inaccessible inside `TwainComponent`.
|
||||||
|
@ -755,10 +750,10 @@ a(href="#top").to-top Back to top
|
||||||
which intercepts all promises issued within the _async_ method call.
|
which intercepts all promises issued within the _async_ method call.
|
||||||
|
|
||||||
The `ComponentFixture.whenStable` method returns its own promise which resolves when the `getQuote` promise completes.
|
The `ComponentFixture.whenStable` method returns its own promise which resolves when the `getQuote` promise completes.
|
||||||
In fact, the _whenStable_ promise resolves when _all pending asynchronous activities_ complete ... the definition of "stable".
|
In fact, the _whenStable_ promise resolves when _all pending asynchronous activities within this test_ complete ... the definition of "stable".
|
||||||
|
|
||||||
Then the testing continues.
|
Then the test resumes and kicks off another round of change detection (`fixture.detectChanges`)
|
||||||
The test kicks off another round of change detection (`fixture.detechChanges`) which tells Angular to update the DOM with the quote.
|
which tells Angular to update the DOM with the quote.
|
||||||
The `getQuote` helper method extracts the display element text and the expectation confirms that the text matches the test quote.
|
The `getQuote` helper method extracts the display element text and the expectation confirms that the text matches the test quote.
|
||||||
|
|
||||||
#fakeAsync
|
#fakeAsync
|
||||||
|
@ -772,23 +767,23 @@ a(href="#top").to-top Back to top
|
||||||
Notice that `fakeAsync` replaces `async` as the `it` argument.
|
Notice that `fakeAsync` replaces `async` as the `it` argument.
|
||||||
The `fakeAsync` function is another of the Angular testing utilities.
|
The `fakeAsync` function is another of the Angular testing utilities.
|
||||||
|
|
||||||
Like [async](#), it _takes_ a parameterless function and _returns_ a parameterless function
|
Like [async](#async), it _takes_ a parameterless function and _returns_ a function
|
||||||
which becomes the argument to the Jasmine `it` call.
|
that becomes the argument to the Jasmine `it` call.
|
||||||
|
|
||||||
The `fakeAsync` function enables a linear coding style by running the test body in a special _fakeAsync test zone_.
|
The `fakeAsync` function enables a linear coding style by running the test body in a special _fakeAsync test zone_.
|
||||||
|
|
||||||
The principle advantage of `fakeAsync` over `async` is that the test appears to be synchronous.
|
The principle advantage of `fakeAsync` over `async` is that the test appears to be synchronous.
|
||||||
There are no promises at all.
|
There is no `then(...)` to disrupt the visible flow of control.
|
||||||
No `then(...)` chains to disrupt the visible flow of control.
|
The promise-returning `fixture.whenStable` is gone, replaced by `tick()`.
|
||||||
|
|
||||||
There are limitations. For example, you cannot make an XHR call from within a `fakeAsync`.
|
.l-sub-section
|
||||||
|
:marked
|
||||||
|
There _are_ limitations. For example, you cannot make an XHR call from within a `fakeAsync`.
|
||||||
|
|
||||||
#tick
|
#tick
|
||||||
#tick-first-look
|
#tick-first-look
|
||||||
:marked
|
:marked
|
||||||
## The _tick_ function
|
## The _tick_ function
|
||||||
Compare the third and fourth tests. Notice that `fixture.whenStable` is gone, replaced by `tick()`.
|
|
||||||
|
|
||||||
The `tick` function is one of the Angular testing utilities and a companion to `fakeAsync`.
|
The `tick` function is one of the Angular testing utilities and a companion to `fakeAsync`.
|
||||||
It can only be called within a `fakeAsync` body.
|
It can only be called within a `fakeAsync` body.
|
||||||
|
|
||||||
|
@ -858,25 +853,26 @@ a(href="#top").to-top Back to top
|
||||||
:marked
|
:marked
|
||||||
## The _async_ function in _beforeEach_
|
## The _async_ function in _beforeEach_
|
||||||
|
|
||||||
Notice the `async` call in the `beforeEach`.
|
Notice the `async` call in the `beforeEach`, made necessary by the asynchronous `TestBed.compileComponents` method.
|
||||||
The `async` function arranges for the tester's code to run in a special _async test zone_
|
The `async` function arranges for the tester's code to run in a special _async test zone_
|
||||||
that hides the mechanics of asynchronous execution, just as it does when passed to an [_it_ test)(#async).
|
that hides the mechanics of asynchronous execution, just as it does when passed to an [_it_ test)(#async).
|
||||||
|
|
||||||
#compile-components
|
#compile-components
|
||||||
:marked
|
:marked
|
||||||
## _compileComponents_
|
## _compileComponents_
|
||||||
In this example, `Testbed.compileComponents` compiles one component, the `DashboardComponent`.
|
In this example, `TestBed.compileComponents` compiles one component, the `DashboardComponent`.
|
||||||
It's the only declared component in this testing module.
|
It's the only declared component in this testing module.
|
||||||
|
|
||||||
Tests later in this chapter have more declared components and some of them import application
|
Tests later in this chapter have more declared components and some of them import application
|
||||||
modules that declare yet more components.
|
modules that declare yet more components.
|
||||||
Some or all of these components could have external templates and css files.
|
Some or all of these components could have external templates and css files.
|
||||||
`TestBed.compileComponents` compiles them all asynchonously at one time.
|
`TestBed.compileComponents` compiles them all asynchronously at one time.
|
||||||
|
|
||||||
The `compileComponents` method returns a promise so you can perform additional tasks _after_ it finishes.
|
The `compileComponents` method returns a promise so you can perform additional tasks _after_ it finishes.
|
||||||
|
The promise isn't needed here.
|
||||||
|
|
||||||
### _compileComponents_ closes configuration
|
### _compileComponents_ closes configuration
|
||||||
After `compileComponents` runs, the current `TestBed` instance is closed to further configuration.
|
Calling `compileComponents` closes the current `TestBed` instance is further configuration.
|
||||||
You cannot call any more `TestBed` configuration methods, not `configureTestModule`
|
You cannot call any more `TestBed` configuration methods, not `configureTestModule`
|
||||||
nor any of the `override...` methods. The `TestBed` throws an error if you try.
|
nor any of the `override...` methods. The `TestBed` throws an error if you try.
|
||||||
|
|
||||||
|
@ -928,7 +924,7 @@ a(href="#top").to-top Back to top
|
||||||
The router seems particularly challenging.
|
The router seems particularly challenging.
|
||||||
.l-sub-section
|
.l-sub-section
|
||||||
:marked
|
:marked
|
||||||
The [discussion below](#routed-component) covers testing components that requre the router.
|
The [discussion below](#routed-component) covers testing components that require the router.
|
||||||
:marked
|
:marked
|
||||||
The immediate goal is to test the `DashboardHeroComponent`, not the `DashboardComponent`, and there's no need
|
The immediate goal is to test the `DashboardHeroComponent`, not the `DashboardComponent`, and there's no need
|
||||||
to work hard unnecessarily. Let's try the second and third options.
|
to work hard unnecessarily. Let's try the second and third options.
|
||||||
|
|
Loading…
Reference in New Issue