{@a top}
# Testing
This guide offers tips and techniques for unit and integration testing Angular applications.
The guide presents tests of a sample application created with the [Angular CLI](cli). This sample application is much like the one created in the [_Tour of Heroes_ tutorial](tutorial).
The sample application and all tests in this guide are available for inspection and experimentation:
- Sample app
- Tests
## Setup
The Angular CLI downloads and installs everything you need to test an Angular application with the [Jasmine test framework](https://jasmine.github.io/).
The project you create with the CLI is immediately ready to test.
Just run the [`ng test`](cli/test) CLI command:
ng test
The `ng test` command builds the app in _watch mode_,
and launches the [Karma test runner](https://karma-runner.github.io).
The console output looks a bit like this:
10% building modules 1/1 modules 0 active
...INFO [karma]: Karma v1.7.1 server started at http://0.0.0.0:9876/
...INFO [launcher]: Launching browser Chrome ...
...INFO [launcher]: Starting browser Chrome
...INFO [Chrome ...]: Connected on socket ...
Chrome ...: Executed 3 of 3 SUCCESS (0.135 secs / 0.205 secs)
The last line of the log is the most important.
It shows that Karma ran three tests that all passed.
A chrome browser also opens and displays the test output in the "Jasmine HTML Reporter" like this.
Most people find this browser output easier to read than the console log.
You can click on a test row to re-run just that test or click on a description to re-run the tests in the selected test group ("test suite").
Meanwhile, the `ng test` command is watching for changes.
To see this in action, make a small change to `app.component.ts` and save.
The tests run again, the browser refreshes, and the new test results appear.
#### Configuration
The CLI takes care of Jasmine and Karma configuration for you.
You can fine-tune many options by editing the `karma.conf.js` and
the `test.ts` files in the `src/` folder.
The `karma.conf.js` file is a partial Karma configuration file.
The CLI constructs the full runtime configuration in memory, based on application structure specified in the `angular.json` file, supplemented by `karma.conf.js`.
Search the web for more details about Jasmine and Karma configuration.
#### Other test frameworks
You can also unit test an Angular app with other testing libraries and test runners.
Each library and runner has its own distinctive installation procedures, configuration, and syntax.
Search the web to learn more.
#### Test file name and location
Look inside the `src/app` folder.
The CLI generated a test file for the `AppComponent` named `app.component.spec.ts`.
The test file extension **must be `.spec.ts`** so that tooling can identify it as a file with tests (AKA, a _spec_ file).
The `app.component.ts` and `app.component.spec.ts` files are siblings in the same folder.
The root file names (`app.component`) are the same for both files.
Adopt these two conventions in your own projects for _every kind_ of test file.
{@a ci}
## Set up continuous integration
One of the best ways to keep your project bug-free is through a test suite, but it's easy to forget to run tests all the time.
Continuous integration (CI) servers let you set up your project repository so that your tests run on every commit and pull request.
There are paid CI services like Circle CI and Travis CI, and you can also host your own for free using Jenkins and others.
Although Circle CI and Travis CI are paid services, they are provided free for open source projects.
You can create a public project on GitHub and add these services without paying.
Contributions to the Angular repo are automatically run through a whole suite of Circle CI tests.
This article explains how to configure your project to run Circle CI and Travis CI, and also update your test configuration to be able to run tests in the Chrome browser in either environment.
### Configure project for Circle CI
Step 1: Create a folder called `.circleci` at the project root.
Step 2: In the new folder, create a file called `config.yml` with the following content:
```
version: 2
jobs:
build:
working_directory: ~/my-project
docker:
- image: circleci/node:10-browsers
steps:
- checkout
- restore_cache:
key: my-project-{{ .Branch }}-{{ checksum "package-lock.json" }}
- run: npm install
- save_cache:
key: my-project-{{ .Branch }}-{{ checksum "package-lock.json" }}
paths:
- "node_modules"
- run: npm run test -- --no-watch --no-progress --browsers=ChromeHeadlessCI
- run: npm run e2e -- --protractor-config=e2e/protractor-ci.conf.js
```
This configuration caches `node_modules/` and uses [`npm run`](https://docs.npmjs.com/cli/run-script) to run CLI commands, because `@angular/cli` is not installed globally.
The double dash (`--`) is needed to pass arguments into the `npm` script.
Step 3: Commit your changes and push them to your repository.
Step 4: [Sign up for Circle CI](https://circleci.com/docs/2.0/first-steps/) and [add your project](https://circleci.com/add-projects).
Your project should start building.
* Learn more about Circle CI from [Circle CI documentation](https://circleci.com/docs/2.0/).
### Configure project for Travis CI
Step 1: Create a file called `.travis.yml` at the project root, with the following content:
```
dist: trusty
sudo: false
language: node_js
node_js:
- "10"
addons:
apt:
sources:
- google-chrome
packages:
- google-chrome-stable
cache:
directories:
- ./node_modules
install:
- npm install
script:
- npm run test -- --no-watch --no-progress --browsers=ChromeHeadlessCI
- npm run e2e -- --protractor-config=e2e/protractor-ci.conf.js
```
This does the same things as the Circle CI configuration, except that Travis doesn't come with Chrome, so we use Chromium instead.
Step 2: Commit your changes and push them to your repository.
Step 3: [Sign up for Travis CI](https://travis-ci.org/auth) and [add your project](https://travis-ci.org/profile).
You'll need to push a new commit to trigger a build.
* Learn more about Travis CI testing from [Travis CI documentation](https://docs.travis-ci.com/).
### Configure CLI for CI testing in Chrome
When the CLI commands `ng test` and `ng e2e` are generally running the CI tests in your environment, you might still need to adjust your configuration to run the Chrome browser tests.
There are configuration files for both the [Karma JavaScript test runner](https://karma-runner.github.io/latest/config/configuration-file.html)
and [Protractor](https://www.protractortest.org/#/api-overview) end-to-end testing tool,
which you must adjust to start Chrome without sandboxing.
We'll be using [Headless Chrome](https://developers.google.com/web/updates/2017/04/headless-chrome#cli) in these examples.
* In the Karma configuration file, `karma.conf.js`, add a custom launcher called ChromeHeadlessCI below browsers:
```
browsers: ['Chrome'],
customLaunchers: {
ChromeHeadlessCI: {
base: 'ChromeHeadless',
flags: ['--no-sandbox']
}
},
```
* In the root folder of your e2e tests project, create a new file named `protractor-ci.conf.js`. This new file extends the original `protractor.conf.js`.
```
const config = require('./protractor.conf').config;
config.capabilities = {
browserName: 'chrome',
chromeOptions: {
args: ['--headless', '--no-sandbox']
}
};
exports.config = config;
```
Now you can run the following commands to use the `--no-sandbox` flag:
ng test --no-watch --no-progress --browsers=ChromeHeadlessCI
ng e2e --protractor-config=e2e/protractor-ci.conf.js
**Note:** Right now, you'll also want to include the `--disable-gpu` flag if you're running on Windows. See [crbug.com/737678](https://crbug.com/737678).
{@a code-coverage}
## Enable code coverage reports
The CLI can run unit tests and create code coverage reports.
Code coverage reports show you any parts of our code base that may not be properly tested by your unit tests.
To generate a coverage report run the following command in the root of your project.
ng test --no-watch --code-coverage
When the tests are complete, the command creates a new `/coverage` folder in the project. Open the `index.html` file to see a report with your source code and code coverage values.
If you want to create code-coverage reports every time you test, you can set the following option in the CLI configuration file, `angular.json`:
```
"test": {
"options": {
"codeCoverage": true
}
}
```
### Code coverage enforcement
The code coverage percentages let you estimate how much of your code is tested.
If your team decides on a set minimum amount to be unit tested, you can enforce this minimum with the Angular CLI.
For example, suppose you want the code base to have a minimum of 80% code coverage.
To enable this, open the [Karma](https://karma-runner.github.io) test platform configuration file, `karma.conf.js`, and add the following in the `coverageIstanbulReporter:` key.
```
coverageIstanbulReporter: {
reports: [ 'html', 'lcovonly' ],
fixWebpackSourcePaths: true,
thresholds: {
statements: 80,
lines: 80,
branches: 80,
functions: 80
}
}
```
The `thresholds` property causes the tool to enforce a minimum of 80% code coverage when the unit tests are run in the project.
## Service Tests
Services are often the easiest files to unit test.
Here are some synchronous and asynchronous unit tests of the `ValueService`
written without assistance from Angular testing utilities.
{@a services-with-dependencies}
#### Services with dependencies
Services often depend on other services that Angular injects into the constructor.
In many cases, it's easy to create and _inject_ these dependencies by hand while
calling the service's constructor.
The `MasterService` is a simple example:
`MasterService` delegates its only method, `getValue`, to the injected `ValueService`.
Here are several ways to test it.
The first test creates a `ValueService` with `new` and passes it to the `MasterService` constructor.
However, injecting the real service rarely works well as most dependent services are difficult to create and control.
Instead you can mock the dependency, use a dummy value, or create a
[spy](https://jasmine.github.io/2.0/introduction.html#section-Spies)
on the pertinent service method.
Prefer spies as they are usually the easiest way to mock services.
These standard testing techniques are great for unit testing services in isolation.
However, you almost always inject services into application classes using Angular
dependency injection and you should have tests that reflect that usage pattern.
Angular testing utilities make it easy to investigate how injected services behave.
#### Testing services with the _TestBed_
Your app relies on Angular [dependency injection (DI)](guide/dependency-injection)
to create services.
When a service has a dependent service, DI finds or creates that dependent service.
And if that dependent service has its own dependencies, DI finds-or-creates them as well.
As service _consumer_, you don't worry about any of this.
You don't worry about the order of constructor arguments or how they're created.
As a service _tester_, you must at least think about the first level of service dependencies
but you _can_ let Angular DI do the service creation and deal with constructor argument order
when you use the `TestBed` testing utility to provide and create services.
{@a testbed}
#### Angular _TestBed_
The `TestBed` is the most important of the Angular testing utilities.
The `TestBed` creates a dynamically-constructed Angular _test_ module that emulates
an Angular [@NgModule](guide/ngmodules).
The `TestBed.configureTestingModule()` method takes a metadata object that can have most of the properties of an [@NgModule](guide/ngmodules).
To test a service, you set the `providers` metadata property with an
array of the services that you'll test or mock.
Then inject it inside a test by calling `TestBed.inject()` with the service class as the argument.
**Note:** We used to have `TestBed.get()` instead of `TestBed.inject()`.
The `get` method wasn't type safe, it always returned `any`, and this is error prone.
We decided to migrate to a new function instead of updating the existing one given
the large scale use that would have an immense amount of breaking changes.
Or inside the `beforeEach()` if you prefer to inject the service as part of your setup.
When testing a service with a dependency, provide the mock in the `providers` array.
In the following example, the mock is a spy object.
The test consumes that spy in the same way it did earlier.
{@a no-before-each}
#### Testing without _beforeEach()_
Most test suites in this guide call `beforeEach()` to set the preconditions for each `it()` test
and rely on the `TestBed` to create classes and inject services.
There's another school of testing that never calls `beforeEach()` and prefers to create classes explicitly rather than use the `TestBed`.
Here's how you might rewrite one of the `MasterService` tests in that style.
Begin by putting re-usable, preparatory code in a _setup_ function instead of `beforeEach()`.
The `setup()` function returns an object literal
with the variables, such as `masterService`, that a test might reference.
You don't define _semi-global_ variables (e.g., `let masterService: MasterService`)
in the body of the `describe()`.
Then each test invokes `setup()` in its first line, before continuing
with steps that manipulate the test subject and assert expectations.
Notice how the test uses
[_destructuring assignment_](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)
to extract the setup variables that it needs.
Many developers feel this approach is cleaner and more explicit than the
traditional `beforeEach()` style.
Although this testing guide follows the traditional style and
the default [CLI schematics](https://github.com/angular/angular-cli)
generate test files with `beforeEach()` and `TestBed`,
feel free to adopt _this alternative approach_ in your own projects.
#### Testing HTTP services
Data services that make HTTP calls to remote servers typically inject and delegate
to the Angular [`HttpClient`](guide/http) service for XHR calls.
You can test a data service with an injected `HttpClient` spy as you would
test any service with a dependency.
The `HeroService` methods return `Observables`. You must
_subscribe_ to an observable to (a) cause it to execute and (b)
assert that the method succeeds or fails.
The `subscribe()` method takes a success (`next`) and fail (`error`) callback.
Make sure you provide _both_ callbacks so that you capture errors.
Neglecting to do so produces an asynchronous uncaught observable error that
the test runner will likely attribute to a completely different test.
#### _HttpClientTestingModule_
Extended interactions between a data service and the `HttpClient` can be complex
and difficult to mock with spies.
The `HttpClientTestingModule` can make these testing scenarios more manageable.
While the _code sample_ accompanying this guide demonstrates `HttpClientTestingModule`,
this page defers to the [Http guide](guide/http#testing-http-requests),
which covers testing with the `HttpClientTestingModule` in detail.
## Component Test Basics
A component, unlike all other parts of an Angular application,
combines an HTML template and a TypeScript class.
The component truly is the template and the class _working together_. To adequately test a component, you should test that they work together
as intended.
Such tests require creating the component's host element in the browser DOM,
as Angular does, and investigating the component class's interaction with
the DOM as described by its template.
The Angular `TestBed` facilitates this kind of testing as you'll see in the sections below.
But in many cases, _testing the component class alone_, without DOM involvement,
can validate much of the component's behavior in an easier, more obvious way.
### Component class testing
Test a component class on its own as you would test a service class.
Consider this `LightswitchComponent` which toggles a light on and off
(represented by an on-screen message) when the user clicks the button.
You might decide only to test that the `clicked()` method
toggles the light's _on/off_ state and sets the message appropriately.
This component class has no dependencies. To test these types of classes, follow the same steps as you would for a service that has no dependencies:
1. Create a component using the new keyword.
2. Poke at its API.
3. Assert expectations on its public state.
Here is the `DashboardHeroComponent` from the _Tour of Heroes_ tutorial.
It appears within the template of a parent component,
which binds a _hero_ to the `@Input` property and
listens for an event raised through the _selected_ `@Output` property.
You can test that the class code works without creating the `DashboardHeroComponent`
or its parent component.
When a component has dependencies, you may wish to use the `TestBed` to both
create the component and its dependencies.
The following `WelcomeComponent` depends on the `UserService` to know the name of the user to greet.
You might start by creating a mock of the `UserService` that meets the minimum needs of this component.
Then provide and inject _both the_ **component** _and the service_ in the `TestBed` configuration.
Then exercise the component class, remembering to call the [lifecycle hook methods](guide/lifecycle-hooks) as Angular does when running the app.
### Component DOM testing
Testing the component _class_ is as easy as testing a service.
But a component is more than just its class.
A component interacts with the DOM and with other components.
The _class-only_ tests can tell you about class behavior.
They cannot tell you if the component is going to render properly,
respond to user input and gestures, or integrate with its parent and child components.
None of the _class-only_ tests above can answer key questions about how the
components actually behave on screen.
- Is `Lightswitch.clicked()` bound to anything such that the user can invoke it?
- Is the `Lightswitch.message` displayed?
- Can the user actually select the hero displayed by `DashboardHeroComponent`?
- Is the hero name displayed as expected (i.e, in uppercase)?
- Is the welcome message displayed by the template of `WelcomeComponent`?
These may not be troubling questions for the simple components illustrated above.
But many components have complex interactions with the DOM elements
described in their templates, causing HTML to appear and disappear as
the component state changes.
To answer these kinds of questions, you have to create the DOM elements associated
with the components, you must examine the DOM to confirm that component state
displays properly at the appropriate times, and you must simulate user interaction
with the screen to determine whether those interactions cause the component to
behave as expected.
To write these kinds of test, you'll use additional features of the `TestBed`
as well as other testing helpers.
#### CLI-generated tests
The CLI creates an initial test file for you by default when you ask it to
generate a new component.
For example, the following CLI command generates a `BannerComponent` in the `app/banner` folder (with inline template and styles):
ng generate component banner --inline-template --inline-style --module app
It also generates an initial test file for the component, `banner-external.component.spec.ts`, that looks like this:
Because `compileComponents` is asynchronous, it uses
the [`async`](api/core/testing/async) utility
function imported from `@angular/core/testing`.
Please refer to the [async](#async) section for more details.
#### Reduce the setup
Only the last three lines of this file actually test the component
and all they do is assert that Angular can create the component.
The rest of the file is boilerplate setup code anticipating more advanced tests that _might_ become necessary if the component evolves into something substantial.
You'll learn about these advanced test features below.
For now, you can radically reduce this test file to a more manageable size:
In this example, the metadata object passed to `TestBed.configureTestingModule`
simply declares `BannerComponent`, the component to test.
There's no need to declare or import anything else.
The default test module is pre-configured with
something like the `BrowserModule` from `@angular/platform-browser`.
Later you'll call `TestBed.configureTestingModule()` with
imports, providers, and more declarations to suit your testing needs.
Optional `override` methods can further fine-tune aspects of the configuration.
{@a create-component}
#### _createComponent()_
After configuring `TestBed`, you call its `createComponent()` method.
`TestBed.createComponent()` creates an instance of the `BannerComponent`,
adds a corresponding element to the test-runner DOM,
and returns a [`ComponentFixture`](#component-fixture).
Do not re-configure `TestBed` after calling `createComponent`.
The `createComponent` method freezes the current `TestBed` definition,
closing it to further configuration.
You cannot call any more `TestBed` configuration methods, not `configureTestingModule()`,
nor `get()`, nor any of the `override...` methods.
If you try, `TestBed` throws an error.
{@a component-fixture}
#### _ComponentFixture_
The [ComponentFixture](api/core/testing/ComponentFixture) is a test harness for interacting with the created component and its corresponding element.
Access the component instance through the fixture and confirm it exists with a Jasmine expectation:
#### _beforeEach()_
You will add more tests as this component evolves.
Rather than duplicate the `TestBed` configuration for each test,
you refactor to pull the setup into a Jasmine `beforeEach()` and some supporting variables:
Now add a test that gets the component's element from `fixture.nativeElement` and
looks for the expected text.
{@a native-element}
#### _nativeElement_
The value of `ComponentFixture.nativeElement` has the `any` type.
Later you'll encounter the `DebugElement.nativeElement` and it too has the `any` type.
Angular can't know at compile time what kind of HTML element the `nativeElement` is or
if it even is an HTML element.
The app might be running on a _non-browser platform_, such as the server or a
[Web Worker](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API),
where the element may have a diminished API or not exist at all.
The tests in this guide are designed to run in a browser so a
`nativeElement` value will always be an `HTMLElement` or
one of its derived classes.
Knowing that it is an `HTMLElement` of some sort, you can use
the standard HTML `querySelector` to dive deeper into the element tree.
Here's another test that calls `HTMLElement.querySelector` to get the paragraph element and look for the banner text:
{@a debug-element}
#### _DebugElement_
The Angular _fixture_ provides the component's element directly through the `fixture.nativeElement`.
This is actually a convenience method, implemented as `fixture.debugElement.nativeElement`.
There's a good reason for this circuitous path to the element.
The properties of the `nativeElement` depend upon the runtime environment.
You could be running these tests on a _non-browser_ platform that doesn't have a DOM or
whose DOM-emulation doesn't support the full `HTMLElement` API.
Angular relies on the `DebugElement` abstraction to work safely across _all supported platforms_.
Instead of creating an HTML element tree, Angular creates a `DebugElement` tree that wraps the _native elements_ for the runtime platform.
The `nativeElement` property unwraps the `DebugElement` and returns the platform-specific element object.
Because the sample tests for this guide are designed to run only in a browser,
a `nativeElement` in these tests is always an `HTMLElement`
whose familiar methods and properties you can explore within a test.
Here's the previous test, re-implemented with `fixture.debugElement.nativeElement`:
The `DebugElement` has other methods and properties that
are useful in tests, as you'll see elsewhere in this guide.
You import the `DebugElement` symbol from the Angular core library.
{@a by-css}
#### _By.css()_
Although the tests in this guide all run in the browser,
some apps might run on a different platform at least some of the time.
For example, the component might render first on the server as part of a strategy to make the application launch faster on poorly connected devices. The server-side renderer might not support the full HTML element API.
If it doesn't support `querySelector`, the previous test could fail.
The `DebugElement` offers query methods that work for all supported platforms.
These query methods take a _predicate_ function that returns `true` when a node in the `DebugElement` tree matches the selection criteria.
You create a _predicate_ with the help of a `By` class imported from a
library for the runtime platform. Here's the `By` import for the browser platform:
The following example re-implements the previous test with
`DebugElement.query()` and the browser's `By.css` method.
Some noteworthy observations:
- The `By.css()` static method selects `DebugElement` nodes
with a [standard CSS selector](https://developer.mozilla.org/en-US/docs/Web/Guide/CSS/Getting_started/Selectors 'CSS selectors').
- The query returns a `DebugElement` for the paragraph.
- You must unwrap that result to get the paragraph element.
When you're filtering by CSS selector and only testing properties of a browser's _native element_, the `By.css` approach may be overkill.
It's often easier and more clear to filter with a standard `HTMLElement` method
such as `querySelector()` or `querySelectorAll()`,
as you'll see in the next set of tests.
## Component Test Scenarios
The following sections, comprising most of this guide, explore common
component testing scenarios
### Component binding
The current `BannerComponent` presents static title text in the HTML template.
After a few changes, the `BannerComponent` presents a dynamic title by binding to
the component's `title` property like this.
Simple as this is, you decide to add a test to confirm that component
actually displays the right content where you think it should.
#### Query for the _<h1>_
You'll write a sequence of tests that inspect the value of the `
` element
that wraps the _title_ property interpolation binding.
You update the `beforeEach` to find that element with a standard HTML `querySelector`
and assign it to the `h1` variable.
{@a detect-changes}
#### _createComponent()_ does not bind data
For your first test you'd like to see that the screen displays the default `title`.
Your instinct is to write a test that immediately inspects the `
` like this:
_That test fails_ with the message:
```javascript
expected '' to contain 'Test Tour of Heroes'.
```
Binding happens when Angular performs **change detection**.
In production, change detection kicks in automatically
when Angular creates a component or the user enters a keystroke or
an asynchronous activity (e.g., AJAX) completes.
The `TestBed.createComponent` does _not_ trigger change detection; a fact confirmed in the revised test:
#### _detectChanges()_
You must tell the `TestBed` to perform data binding by calling `fixture.detectChanges()`.
Only then does the `
` have the expected title.
Delayed change detection is intentional and useful.
It gives the tester an opportunity to inspect and change the state of
the component _before Angular initiates data binding and calls [lifecycle hooks](guide/lifecycle-hooks)_.
Here's another test that changes the component's `title` property _before_ calling `fixture.detectChanges()`.
{@a auto-detect-changes}
#### Automatic change detection
The `BannerComponent` tests frequently call `detectChanges`.
Some testers prefer that the Angular test environment run change detection automatically.
That's possible by configuring the `TestBed` with the `ComponentFixtureAutoDetect` provider.
First import it from the testing utility library:
Then add it to the `providers` array of the testing module configuration:
Here are three tests that illustrate how automatic change detection works.
The first test shows the benefit of automatic change detection.
The second and third test reveal an important limitation.
The Angular testing environment does _not_ know that the test changed the component's `title`.
The `ComponentFixtureAutoDetect` service responds to _asynchronous activities_ such as promise resolution, timers, and DOM events.
But a direct, synchronous update of the component property is invisible.
The test must call `fixture.detectChanges()` manually to trigger another cycle of change detection.
Rather than wonder when the test fixture will or won't perform change detection,
the samples in this guide _always call_ `detectChanges()` _explicitly_.
There is no harm in calling `detectChanges()` more often than is strictly necessary.
{@a dispatch-event}
#### Change an input value with _dispatchEvent()_
To simulate user input, you can find the input element and set its `value` property.
You will call `fixture.detectChanges()` to trigger Angular's change detection.
But there is an essential, intermediate step.
Angular doesn't know that you set the input element's `value` property.
It won't read that property until you raise the element's `input` event by calling `dispatchEvent()`.
_Then_ you call `detectChanges()`.
The following example demonstrates the proper sequence.
### Component with external files
The `BannerComponent` above is defined with an _inline template_ and _inline css_, specified in the `@Component.template` and `@Component.styles` properties respectively.
Many components specify _external templates_ and _external css_ with the
`@Component.templateUrl` and `@Component.styleUrls` properties respectively,
as the following variant of `BannerComponent` does.
This syntax tells the Angular compiler to read the external files during component compilation.
That's not a problem when you run the CLI `ng test` command because it
_compiles the app before running the tests_.
However, if you run the tests in a **non-CLI environment**,
tests of this component may fail.
For example, if you run the `BannerComponent` tests in a web coding environment such as [plunker](https://plnkr.co/), you'll see a message like this one:
Error: This test module uses the component BannerComponent
which is using a "templateUrl" or "styleUrls", but they were never compiled.
Please call "TestBed.compileComponents" before your test.
You get this test failure message when the runtime environment
compiles the source code _during the tests themselves_.
To correct the problem, call `compileComponents()` as explained [below](#compile-components).
{@a component-with-dependency}
### Component with a dependency
Components often have service dependencies.
The `WelcomeComponent` displays a welcome message to the logged in user.
It knows who the user is based on a property of the injected `UserService`:
The `WelcomeComponent` has decision logic that interacts with the service, logic that makes this component worth testing.
Here's the testing module configuration for the spec file, `app/welcome/welcome.component.spec.ts`:
This time, in addition to declaring the _component-under-test_,
the configuration adds a `UserService` provider to the `providers` list.
But not the real `UserService`.
{@a service-test-doubles}
#### Provide service test doubles
A _component-under-test_ doesn't have to be injected with real services.
In fact, it is usually better if they are test doubles (stubs, fakes, spies, or mocks).
The purpose of the spec is to test the component, not the service,
and real services can be trouble.
Injecting the real `UserService` could be a nightmare.
The real service might ask the user for login credentials and
attempt to reach an authentication server.
These behaviors can be hard to intercept.
It is far easier and safer to create and register a test double in place of the real `UserService`.
This particular test suite supplies a minimal mock of the `UserService` that satisfies the needs of the `WelcomeComponent` and its tests:
{@a get-injected-service}
#### Get injected services
The tests need access to the (stub) `UserService` injected into the `WelcomeComponent`.
Angular has a hierarchical injection system.
There can be injectors at multiple levels, from the root injector created by the `TestBed`
down through the component tree.
The safest way to get the injected service, the way that **_always works_**,
is to **get it from the injector of the _component-under-test_**.
The component injector is a property of the fixture's `DebugElement`.
{@a testbed-inject}
#### _TestBed.inject()_
You _may_ also be able to get the service from the root injector via `TestBed.inject()`.
This is easier to remember and less verbose.
But it only works when Angular injects the component with the service instance in the test's root injector.
In this test suite, the _only_ provider of `UserService` is the root testing module,
so it is safe to call `TestBed.inject()` as follows:
For a use case in which `TestBed.inject()` does not work,
see the [_Override component providers_](#component-override) section that
explains when and why you must get the service from the component's injector instead.
{@a welcome-spec-setup}
#### Final setup and tests
Here's the complete `beforeEach()`, using `TestBed.inject()`:
And here are some tests:
The first is a sanity test; it confirms that the stubbed `UserService` is called and working.
The second parameter to the Jasmine matcher (e.g., `'expected name'`) is an optional failure label.
If the expectation fails, Jasmine appends this label to the expectation failure message.
In a spec with multiple expectations, it can help clarify what went wrong and which expectation failed.
The remaining tests confirm the logic of the component when the service returns different values.
The second test validates the effect of changing the user name.
The third test checks that the component displays the proper message when there is no logged-in user.
{@a component-with-async-service}
### Component with async service
In this sample, the `AboutComponent` template hosts a `TwainComponent`.
The `TwainComponent` displays Mark Twain quotes.
Note that the value of the component's `quote` property passes through an `AsyncPipe`.
That means the property returns either a `Promise` or an `Observable`.
In this example, the `TwainComponent.getQuote()` method tells you that
the `quote` property returns an `Observable`.
The `TwainComponent` gets quotes from an injected `TwainService`.
The component starts the returned `Observable` with a placeholder value (`'...'`),
before the service can return its first quote.
The `catchError` intercepts service errors, prepares an error message,
and returns the placeholder value on the success channel.
It must wait a tick to set the `errorMessage`
in order to avoid updating that message twice in the same change detection cycle.
These are all features you'll want to test.
#### Testing with a spy
When testing a component, only the service's public API should matter.
In general, tests themselves should not make calls to remote servers.
They should emulate such calls. The setup in this `app/twain/twain.component.spec.ts` shows one way to do that:
{@a service-spy}
Focus on the spy.
The spy is designed such that any call to `getQuote` receives an observable with a test quote.
Unlike the real `getQuote()` method, this spy bypasses the server
and returns a synchronous observable whose value is available immediately.
You can write many useful tests with this spy, even though its `Observable` is synchronous.
{@a sync-tests}
#### Synchronous tests
A key advantage of a synchronous `Observable` is that
you can often turn asynchronous processes into synchronous tests.
Because the spy result returns synchronously, the `getQuote()` method updates
the message on screen immediately _after_
the first change detection cycle during which Angular calls `ngOnInit`.
You're not so lucky when testing the error path.
Although the service spy will return an error synchronously,
the component method calls `setTimeout()`.
The test must wait at least one full turn of the JavaScript engine before the
value becomes available. The test must become _asynchronous_.
{@a fake-async}
#### Async test with _fakeAsync()_
To use `fakeAsync()` functionality, you must import `zone.js/dist/zone-testing` in your test setup file.
If you created your project with the Angular CLI, `zone-testing` is already imported in `src/test.ts`.
The following test confirms the expected behavior when the service returns an `ErrorObservable`.
Note that the `it()` function receives an argument of the following form.
```javascript
fakeAsync(() => { /* test body */ })
```
The `fakeAsync()` function enables a linear coding style by running the test body in a special `fakeAsync test zone`.
The test body appears to be synchronous.
There is no nested syntax (like a `Promise.then()`) to disrupt the flow of control.
Limitation: The `fakeAsync()` function won't work if the test body makes an `XMLHttpRequest` (XHR) call.
XHR calls within a test are rare, but if you need to call XHR, see [`async()`](#async), below.
{@a tick}
#### The _tick()_ function
You do have to call [tick()](api/core/testing/tick) to advance the (virtual) clock.
Calling [tick()](api/core/testing/tick) simulates the passage of time until all pending asynchronous activities finish.
In this case, it waits for the error handler's `setTimeout()`.
The [tick()](api/core/testing/tick) function accepts milliseconds and tickOptions as parameters, the millisecond (defaults to 0 if not provided) parameter represents how much the virtual clock advances. For example, if you have a `setTimeout(fn, 100)` in a `fakeAsync()` test, you need to use tick(100) to trigger the fn callback. The tickOptions is an optional parameter with a property called `processNewMacroTasksSynchronously` (defaults to true) represents whether to invoke new generated macro tasks when ticking.
The [tick()](api/core/testing/tick) function is one of the Angular testing utilities that you import with `TestBed`.
It's a companion to `fakeAsync()` and you can only call it within a `fakeAsync()` body.
#### tickOptions
In this example, we have a new macro task (nested setTimeout), by default, when we `tick`, the setTimeout `outside` and `nested` will both be triggered.
And in some case, we don't want to trigger the new macro task when ticking, we can use `tick(milliseconds, {processNewMacroTasksSynchronously: false})` to not invoke new macro task.
#### Comparing dates inside fakeAsync()
`fakeAsync()` simulates passage of time, which allows you to calculate the difference between dates inside `fakeAsync()`.
#### jasmine.clock with fakeAsync()
Jasmine also provides a `clock` feature to mock dates. Angular automatically runs tests that are run after
`jasmine.clock().install()` is called inside a `fakeAsync()` method until `jasmine.clock().uninstall()` is called. `fakeAsync()` is not needed and throws an error if nested.
By default, this feature is disabled. To enable it, set a global flag before importing `zone-testing`.
If you use the Angular CLI, configure this flag in `src/test.ts`.
```
(window as any)['__zone_symbol__fakeAsyncPatchLock'] = true;
import 'zone.js/dist/zone-testing';
```
#### Using the RxJS scheduler inside fakeAsync()
You can also use RxJS scheduler in `fakeAsync()` just like using `setTimeout()` or `setInterval()`, but you need to import `zone.js/dist/zone-patch-rxjs-fake-async` to patch RxJS scheduler.
#### Support more macroTasks
By default, `fakeAsync()` supports the following macro tasks.
- `setTimeout`
- `setInterval`
- `requestAnimationFrame`
- `webkitRequestAnimationFrame`
- `mozRequestAnimationFrame`
If you run other macro tasks such as `HTMLCanvasElement.toBlob()`, an _"Unknown macroTask scheduled in fake async test"_ error will be thrown.
If you want to support such a case, you need to define the macro task you want to support in `beforeEach()`.
For example:
Note that in order to make the `