angular-cn/aio/dist/generated/docs/guide/testing-components-scenarios.json

5 lines
156 KiB
JSON

{
"id": "guide/testing-components-scenarios",
"title": "Component testing scenarios",
"contents": "\n\n\n<div class=\"github-links\">\n <a href=\"https://github.com/angular/angular/edit/master/aio/content/guide/testing-components-scenarios.md?message=docs%3A%20describe%20your%20change...\" aria-label=\"Suggest Edits\" title=\"Suggest Edits\"><i class=\"material-icons\" aria-hidden=\"true\" role=\"img\">mode_edit</i></a>\n</div>\n\n\n<div class=\"content\">\n <h1 id=\"component-testing-scenarios\">Component testing scenarios<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#component-testing-scenarios\"><i class=\"material-icons\">link</i></a></h1>\n<p>This guide explores common component testing use cases.</p>\n<div class=\"alert is-helpful\">\n<p> For the sample app that the testing guides describe, see the <live-example name=\"testing\" embedded-style=\"\" nodownload=\"\">sample app</live-example>.</p>\n<p> For the tests features in the testing guides, see <live-example name=\"testing\" stackblitz=\"specs\" nodownload=\"\">tests</live-example>.</p>\n</div>\n<h2 id=\"component-binding\">Component binding<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#component-binding\"><i class=\"material-icons\">link</i></a></h2>\n<p>In the example app, the <code>BannerComponent</code> presents static title text in the HTML template.</p>\n<p>After a few changes, the <code>BannerComponent</code> presents a dynamic title by binding to\nthe component's <code>title</code> property like this.</p>\n<code-example path=\"testing/src/app/banner/banner.component.ts\" region=\"component\" header=\"app/banner/banner.component.ts\">\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-banner',\n template: '&#x3C;h1>{{title}}&#x3C;/h1>',\n styles: ['h1 { color: green; font-size: 350%}']\n})\nexport class BannerComponent {\n title = 'Test Tour of Heroes';\n}\n\n</code-example>\n<p>As minimal as this is, you decide to add a test to confirm that component\nactually displays the right content where you think it should.</p>\n<h4 id=\"query-for-the-h1\">Query for the <em>&#x3C;h1></em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#query-for-the-h1\"><i class=\"material-icons\">link</i></a></h4>\n<p>You'll write a sequence of tests that inspect the value of the <code>&#x3C;h1></code> element\nthat wraps the <em>title</em> property interpolation binding.</p>\n<p>You update the <code>beforeEach</code> to find that element with a standard HTML <code>querySelector</code>\nand assign it to the <code>h1</code> variable.</p>\n<code-example path=\"testing/src/app/banner/banner.component.spec.ts\" region=\"setup\" header=\"app/banner/banner.component.spec.ts (setup)\">\nlet component: BannerComponent;\nlet fixture: <a href=\"api/core/testing/ComponentFixture\" class=\"code-anchor\">ComponentFixture</a>&#x3C;BannerComponent>;\nlet h1: HTMLElement;\n\nbeforeEach(() => {\n TestBed.configureTestingModule({\n declarations: [ BannerComponent ],\n });\n fixture = TestBed.createComponent(BannerComponent);\n component = fixture.componentInstance; // BannerComponent test instance\n h1 = fixture.nativeElement.querySelector('h1');\n});\n\n</code-example>\n<a id=\"detect-changes\"></a>\n<h4 id=\"createcomponent-does-not-bind-data\"><em>createComponent()</em> does not bind data<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#createcomponent-does-not-bind-data\"><i class=\"material-icons\">link</i></a></h4>\n<p>For your first test you'd like to see that the screen displays the default <code>title</code>.\nYour instinct is to write a test that immediately inspects the <code>&#x3C;h1></code> like this:</p>\n<code-example path=\"testing/src/app/banner/banner.component.spec.ts\" region=\"expect-h1-default-v1\">\nit('should display original title', () => {\n expect(h1.textContent).toContain(component.title);\n});\n\n</code-example>\n<p><em>That test fails</em> with the message:</p>\n<code-example language=\"javascript\">\nexpected '' to contain 'Test Tour of Heroes'.\n</code-example>\n<p>Binding happens when Angular performs <strong>change detection</strong>.</p>\n<p>In production, change detection kicks in automatically\nwhen Angular creates a component or the user enters a keystroke or\nan asynchronous activity (e.g., AJAX) completes.</p>\n<p>The <code>TestBed.createComponent</code> does <em>not</em> trigger change detection; a fact confirmed in the revised test:</p>\n<code-example path=\"testing/src/app/banner/banner.component.spec.ts\" region=\"test-w-o-detect-changes\">\nit('no title in the DOM after createComponent()', () => {\n expect(h1.textContent).toEqual('');\n});\n\n</code-example>\n<h4 id=\"detectchanges\"><em>detectChanges()</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#detectchanges\"><i class=\"material-icons\">link</i></a></h4>\n<p>You must tell the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> to perform data binding by calling <code>fixture.detectChanges()</code>.\nOnly then does the <code>&#x3C;h1></code> have the expected title.</p>\n<code-example path=\"testing/src/app/banner/banner.component.spec.ts\" region=\"expect-h1-default\">\nit('should display original title after detectChanges()', () => {\n fixture.detectChanges();\n expect(h1.textContent).toContain(component.title);\n});\n\n</code-example>\n<p>Delayed change detection is intentional and useful.\nIt gives the tester an opportunity to inspect and change the state of\nthe component <em>before Angular initiates data binding and calls <a href=\"guide/lifecycle-hooks\">lifecycle hooks</a></em>.</p>\n<p>Here's another test that changes the component's <code>title</code> property <em>before</em> calling <code>fixture.detectChanges()</code>.</p>\n<code-example path=\"testing/src/app/banner/banner.component.spec.ts\" region=\"after-change\">\nit('should display a different test title', () => {\n component.title = 'Test <a href=\"api/platform-browser/Title\" class=\"code-anchor\">Title</a>';\n fixture.detectChanges();\n expect(h1.textContent).toContain('Test <a href=\"api/platform-browser/Title\" class=\"code-anchor\">Title</a>');\n});\n\n</code-example>\n<a id=\"auto-detect-changes\"></a>\n<h4 id=\"automatic-change-detection\">Automatic change detection<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#automatic-change-detection\"><i class=\"material-icons\">link</i></a></h4>\n<p>The <code>BannerComponent</code> tests frequently call <code>detectChanges</code>.\nSome testers prefer that the Angular test environment run change detection automatically.</p>\n<p>That's possible by configuring the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> with the <code><a href=\"api/core/testing/ComponentFixtureAutoDetect\" class=\"code-anchor\">ComponentFixtureAutoDetect</a></code> provider.\nFirst import it from the testing utility library:</p>\n<code-example path=\"testing/src/app/banner/banner.component.detect-changes.spec.ts\" region=\"import-ComponentFixtureAutoDetect\" header=\"app/banner/banner.component.detect-changes.spec.ts (import)\">\nimport { <a href=\"api/core/testing/ComponentFixtureAutoDetect\" class=\"code-anchor\">ComponentFixtureAutoDetect</a> } from '@angular/core/testing';\n\n</code-example>\n<p>Then add it to the <code>providers</code> array of the testing module configuration:</p>\n<code-example path=\"testing/src/app/banner/banner.component.detect-changes.spec.ts\" region=\"auto-detect\" header=\"app/banner/banner.component.detect-changes.spec.ts (AutoDetect)\">\nTestBed.configureTestingModule({\n declarations: [ BannerComponent ],\n providers: [\n { provide: <a href=\"api/core/testing/ComponentFixtureAutoDetect\" class=\"code-anchor\">ComponentFixtureAutoDetect</a>, useValue: true }\n ]\n});\n\n</code-example>\n<p>Here are three tests that illustrate how automatic change detection works.</p>\n<code-example path=\"testing/src/app/banner/banner.component.detect-changes.spec.ts\" region=\"auto-detect-tests\" header=\"app/banner/banner.component.detect-changes.spec.ts (AutoDetect Tests)\">\nit('should display original title', () => {\n // Hooray! No `fixture.detectChanges()` needed\n expect(h1.textContent).toContain(comp.title);\n});\n\nit('should still see original title after comp.title change', () => {\n const oldTitle = comp.title;\n comp.title = 'Test <a href=\"api/platform-browser/Title\" class=\"code-anchor\">Title</a>';\n // Displayed title is old because Angular didn't hear the change :(\n expect(h1.textContent).toContain(oldTitle);\n});\n\nit('should display updated title after detectChanges', () => {\n comp.title = 'Test <a href=\"api/platform-browser/Title\" class=\"code-anchor\">Title</a>';\n fixture.detectChanges(); // detect changes explicitly\n expect(h1.textContent).toContain(comp.title);\n});\n\n</code-example>\n<p>The first test shows the benefit of automatic change detection.</p>\n<p>The second and third test reveal an important limitation.\nThe Angular testing environment does <em>not</em> know that the test changed the component's <code>title</code>.\nThe <code><a href=\"api/core/testing/ComponentFixtureAutoDetect\" class=\"code-anchor\">ComponentFixtureAutoDetect</a></code> service responds to <em>asynchronous activities</em> such as promise resolution, timers, and DOM events.\nBut a direct, synchronous update of the component property is invisible.\nThe test must call <code>fixture.detectChanges()</code> manually to trigger another cycle of change detection.</p>\n<div class=\"alert is-helpful\">\n<p>Rather than wonder when the test fixture will or won't perform change detection,\nthe samples in this guide <em>always call</em> <code>detectChanges()</code> <em>explicitly</em>.\nThere is no harm in calling <code>detectChanges()</code> more often than is strictly necessary.</p>\n</div>\n<a id=\"dispatch-event\"></a>\n<h4 id=\"change-an-input-value-with-dispatchevent\">Change an input value with <em>dispatchEvent()</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#change-an-input-value-with-dispatchevent\"><i class=\"material-icons\">link</i></a></h4>\n<p>To simulate user input, you can find the input element and set its <code>value</code> property.</p>\n<p>You will call <code>fixture.detectChanges()</code> to trigger Angular's change detection.\nBut there is an essential, intermediate step.</p>\n<p>Angular doesn't know that you set the input element's <code>value</code> property.\nIt won't read that property until you raise the element's <code>input</code> event by calling <code>dispatchEvent()</code>.\n<em>Then</em> you call <code>detectChanges()</code>.</p>\n<p>The following example demonstrates the proper sequence.</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"title-case-pipe\" header=\"app/hero/hero-detail.component.spec.ts (pipe test)\">\nit('should convert hero name to <a href=\"api/platform-browser/Title\" class=\"code-anchor\">Title</a> Case', () => {\n // get the name's input and display elements from the DOM\n const hostElement = fixture.nativeElement;\n const nameInput: HTMLInputElement = hostElement.querySelector('input');\n const nameDisplay: HTMLElement = hostElement.querySelector('span');\n\n // simulate user entering a new name into the input box\n nameInput.value = 'quick BROWN fOx';\n\n // Dispatch a DOM event so that Angular learns of input value change.\n // In older browsers, such as IE, you might need a CustomEvent instead. See\n // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill\n nameInput.dispatchEvent(new <a href=\"api/router/Event\" class=\"code-anchor\">Event</a>('input'));\n\n // Tell Angular to update the display binding through the title pipe\n fixture.detectChanges();\n\n expect(nameDisplay.textContent).toBe('Quick Brown Fox');\n});\n\n</code-example>\n<h2 id=\"component-with-external-files\">Component with external files<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#component-with-external-files\"><i class=\"material-icons\">link</i></a></h2>\n<p>The <code>BannerComponent</code> above is defined with an <em>inline template</em> and <em>inline css</em>, specified in the <code>@<a href=\"api/core/Component#template\" class=\"code-anchor\">Component.template</a></code> and <code>@<a href=\"api/core/Component#styles\" class=\"code-anchor\">Component.styles</a></code> properties respectively.</p>\n<p>Many components specify <em>external templates</em> and <em>external css</em> with the\n<code>@<a href=\"api/core/Component#templateUrl\" class=\"code-anchor\">Component.templateUrl</a></code> and <code>@<a href=\"api/core/Component#styleUrls\" class=\"code-anchor\">Component.styleUrls</a></code> properties respectively,\nas the following variant of <code>BannerComponent</code> does.</p>\n<code-example path=\"testing/src/app/banner/banner-external.component.ts\" region=\"metadata\" header=\"app/banner/banner-external.component.ts (metadata)\">\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-banner',\n templateUrl: './banner-external.component.html',\n styleUrls: ['./banner-external.component.css']\n})\n\n</code-example>\n<p>This syntax tells the Angular compiler to read the external files during component compilation.</p>\n<p>That's not a problem when you run the CLI <code>ng test</code> command because it\n<em>compiles the app before running the tests</em>.</p>\n<p>However, if you run the tests in a <strong>non-CLI environment</strong>,\ntests of this component may fail.\nFor example, if you run the <code>BannerComponent</code> tests in a web coding environment such as <a href=\"https://plnkr.co/\">plunker</a>, you'll see a message like this one:</p>\n<code-example language=\"sh\" class=\"code-shell\" hidecopy=\"\">\nError: This test module uses the component BannerComponent\nwhich is using a \"templateUrl\" or \"styleUrls\", but they were never compiled.\nPlease call \"TestBed.compileComponents\" before your test.\n</code-example>\n<p>You get this test failure message when the runtime environment\ncompiles the source code <em>during the tests themselves</em>.</p>\n<p>To correct the problem, call <code>compileComponents()</code> as explained <a href=\"guide/testing-components-scenarios#compile-components\">below</a>.</p>\n<a id=\"component-with-dependency\"></a>\n<h2 id=\"component-with-a-dependency\">Component with a dependency<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#component-with-a-dependency\"><i class=\"material-icons\">link</i></a></h2>\n<p>Components often have service dependencies.</p>\n<p>The <code>WelcomeComponent</code> displays a welcome message to the logged in user.\nIt knows who the user is based on a property of the injected <code>UserService</code>:</p>\n<code-example path=\"testing/src/app/welcome/welcome.component.ts\" header=\"app/welcome/welcome.component.ts\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a>, <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> } from '@angular/core';\nimport { UserService } from '../model/user.service';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-welcome',\n template: '&#x3C;h3 class=\"welcome\">&#x3C;i>{{welcome}}&#x3C;/i>&#x3C;/h3>'\n})\nexport class WelcomeComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n welcome: string;\n constructor(private userService: UserService) { }\n\n ngOnInit(): void {\n this.welcome = this.userService.isLoggedIn ?\n 'Welcome, ' + this.userService.user.name : 'Please log in.';\n }\n}\n\n\n</code-example>\n<p>The <code>WelcomeComponent</code> has decision logic that interacts with the service, logic that makes this component worth testing.\nHere's the testing module configuration for the spec file:</p>\n<code-example path=\"testing/src/app/welcome/welcome.component.spec.ts\" region=\"config-test-module\" header=\"app/welcome/welcome.component.spec.ts\">\nTestBed.configureTestingModule({\n declarations: [ WelcomeComponent ],\n// providers: [ UserService ], // NO! Don't provide the real service!\n // Provide a test-double instead\n providers: [ { provide: UserService, useValue: userServiceStub } ],\n});\n\n</code-example>\n<p>This time, in addition to declaring the <em>component-under-test</em>,\nthe configuration adds a <code>UserService</code> provider to the <code>providers</code> list.\nBut not the real <code>UserService</code>.</p>\n<a id=\"service-test-doubles\"></a>\n<h4 id=\"provide-service-test-doubles\">Provide service test doubles<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#provide-service-test-doubles\"><i class=\"material-icons\">link</i></a></h4>\n<p>A <em>component-under-test</em> doesn't have to be injected with real services.\nIn fact, it is usually better if they are test doubles (stubs, fakes, spies, or mocks).\nThe purpose of the spec is to test the component, not the service,\nand real services can be trouble.</p>\n<p>Injecting the real <code>UserService</code> could be a nightmare.\nThe real service might ask the user for login credentials and\nattempt to reach an authentication server.\nThese behaviors can be hard to intercept.\nIt is far easier and safer to create and register a test double in place of the real <code>UserService</code>.</p>\n<p>This particular test suite supplies a minimal mock of the <code>UserService</code> that satisfies the needs of the <code>WelcomeComponent</code> and its tests:</p>\n<code-example path=\"testing/src/app/welcome/welcome.component.spec.ts\" region=\"user-service-stub\" header=\"app/welcome/welcome.component.spec.ts\">\nlet userServiceStub: Partial&#x3C;UserService>;\n\n userServiceStub = {\n isLoggedIn: true,\n user: { name: 'Test User' },\n };\n\n</code-example>\n<a id=\"get-injected-service\"></a>\n<h4 id=\"get-injected-services\">Get injected services<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#get-injected-services\"><i class=\"material-icons\">link</i></a></h4>\n<p>The tests need access to the (stub) <code>UserService</code> injected into the <code>WelcomeComponent</code>.</p>\n<p>Angular has a hierarchical injection system.\nThere can be injectors at multiple levels, from the root injector created by the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code>\ndown through the component tree.</p>\n<p>The safest way to get the injected service, the way that <strong><em>always works</em></strong>,\nis to <strong>get it from the injector of the <em>component-under-test</em></strong>.\nThe component injector is a property of the fixture's <code><a href=\"api/core/DebugElement\" class=\"code-anchor\">DebugElement</a></code>.</p>\n<code-example path=\"testing/src/app/welcome/welcome.component.spec.ts\" region=\"injected-service\" header=\"WelcomeComponent&#x27;s injector\">\n// UserService actually injected into the component\nuserService = fixture.debugElement.injector.get(UserService);\n\n</code-example>\n<a id=\"testbed-inject\"></a>\n<h4 id=\"testbedinject\"><em>TestBed.inject()</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#testbedinject\"><i class=\"material-icons\">link</i></a></h4>\n<p>You <em>may</em> also be able to get the service from the root injector via <code>TestBed.inject()</code>.\nThis is easier to remember and less verbose.\nBut it only works when Angular injects the component with the service instance in the test's root injector.</p>\n<p>In this test suite, the <em>only</em> provider of <code>UserService</code> is the root testing module,\nso it is safe to call <code>TestBed.inject()</code> as follows:</p>\n<code-example path=\"testing/src/app/welcome/welcome.component.spec.ts\" region=\"inject-from-testbed\" header=\"TestBed injector\">\n// UserService from the root injector\nuserService = TestBed.inject(UserService);\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p>For a use case in which <code>TestBed.inject()</code> does not work,\nsee the <a href=\"guide/testing-components-scenarios#component-override\"><em>Override component providers</em></a> section that\nexplains when and why you must get the service from the component's injector instead.</p>\n</div>\n<a id=\"welcome-spec-setup\"></a>\n<h4 id=\"final-setup-and-tests\">Final setup and tests<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#final-setup-and-tests\"><i class=\"material-icons\">link</i></a></h4>\n<p>Here's the complete <code>beforeEach()</code>, using <code>TestBed.inject()</code>:</p>\n<code-example path=\"testing/src/app/welcome/welcome.component.spec.ts\" region=\"setup\" header=\"app/welcome/welcome.component.spec.ts\">\nlet userServiceStub: Partial&#x3C;UserService>;\n\nbeforeEach(() => {\n // stub UserService for test purposes\n userServiceStub = {\n isLoggedIn: true,\n user: { name: 'Test User' },\n };\n\n TestBed.configureTestingModule({\n declarations: [ WelcomeComponent ],\n providers: [ { provide: UserService, useValue: userServiceStub } ],\n });\n\n fixture = TestBed.createComponent(WelcomeComponent);\n comp = fixture.componentInstance;\n\n // UserService from the root injector\n userService = TestBed.inject(UserService);\n\n // get the \"welcome\" element by CSS selector (e.g., by class name)\n el = fixture.nativeElement.querySelector('.welcome');\n});\n\n</code-example>\n<p>And here are some tests:</p>\n<code-example path=\"testing/src/app/welcome/welcome.component.spec.ts\" region=\"tests\" header=\"app/welcome/welcome.component.spec.ts\">\nit('should welcome the user', () => {\n fixture.detectChanges();\n const content = el.textContent;\n expect(content).toContain('Welcome', '\"Welcome ...\"');\n expect(content).toContain('Test User', 'expected name');\n});\n\nit('should welcome \"Bubba\"', () => {\n userService.user.name = 'Bubba'; // welcome message hasn't been shown yet\n fixture.detectChanges();\n expect(el.textContent).toContain('Bubba');\n});\n\nit('should request login if not logged in', () => {\n userService.isLoggedIn = false; // welcome message hasn't been shown yet\n fixture.detectChanges();\n const content = el.textContent;\n expect(content).not.toContain('Welcome', 'not welcomed');\n expect(content).toMatch(/log in/i, '\"log in\"');\n});\n\n</code-example>\n<p>The first is a sanity test; it confirms that the stubbed <code>UserService</code> is called and working.</p>\n<div class=\"alert is-helpful\">\n<p>The second parameter to the Jasmine matcher (e.g., <code>'expected name'</code>) is an optional failure label.\nIf the expectation fails, Jasmine appends this label to the expectation failure message.\nIn a spec with multiple expectations, it can help clarify what went wrong and which expectation failed.</p>\n</div>\n<p>The remaining tests confirm the logic of the component when the service returns different values.\nThe second test validates the effect of changing the user name.\nThe third test checks that the component displays the proper message when there is no logged-in user.</p>\n<a id=\"component-with-async-service\"></a>\n<h2 id=\"component-with-async-service\">Component with async service<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#component-with-async-service\"><i class=\"material-icons\">link</i></a></h2>\n<p>In this sample, the <code>AboutComponent</code> template hosts a <code>TwainComponent</code>.\nThe <code>TwainComponent</code> displays Mark Twain quotes.</p>\n<code-example path=\"testing/src/app/twain/twain.component.ts\" region=\"template\" header=\"app/twain/twain.component.ts (template)\">\ntemplate: `\n &#x3C;p class=\"twain\">&#x3C;i>{{quote | <a href=\"api/common/AsyncPipe\" class=\"code-anchor\">async</a>}}&#x3C;/i>&#x3C;/p>\n &#x3C;button (click)=\"getQuote()\">Next quote&#x3C;/button>\n &#x3C;p class=\"error\" *<a href=\"api/common/NgIf\" class=\"code-anchor\">ngIf</a>=\"errorMessage\">{{ errorMessage }}&#x3C;/p>`,\n\n</code-example>\n<p>Note that the value of the component's <code>quote</code> property passes through an <code><a href=\"api/common/AsyncPipe\" class=\"code-anchor\">AsyncPipe</a></code>.\nThat means the property returns either a <code>Promise</code> or an <code>Observable</code>.</p>\n<p>In this example, the <code>TwainComponent.getQuote()</code> method tells you that\nthe <code>quote</code> property returns an <code>Observable</code>.</p>\n<code-example path=\"testing/src/app/twain/twain.component.ts\" region=\"get-quote\" header=\"app/twain/twain.component.ts (getQuote)\">\ngetQuote() {\n this.errorMessage = '';\n this.quote = this.twainService.getQuote().pipe(\n startWith('...'),\n catchError( (err: any) => {\n // Wait a turn because errorMessage already set once this turn\n setTimeout(() => this.errorMessage = err.message || err.toString());\n return of('...'); // reset message to placeholder\n })\n );\n\n</code-example>\n<p>The <code>TwainComponent</code> gets quotes from an injected <code>TwainService</code>.\nThe component starts the returned <code>Observable</code> with a placeholder value (<code>'...'</code>),\nbefore the service can return its first quote.</p>\n<p>The <code>catchError</code> intercepts service errors, prepares an error message,\nand returns the placeholder value on the success channel.\nIt must wait a tick to set the <code>errorMessage</code>\nin order to avoid updating that message twice in the same change detection cycle.</p>\n<p>These are all features you'll want to test.</p>\n<h4 id=\"testing-with-a-spy\">Testing with a spy<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#testing-with-a-spy\"><i class=\"material-icons\">link</i></a></h4>\n<p>When testing a component, only the service's public API should matter.\nIn general, tests themselves should not make calls to remote servers.\nThey should emulate such calls. The setup in this <code>app/twain/twain.component.spec.ts</code> shows one way to do that:</p>\n<code-example path=\"testing/src/app/twain/twain.component.spec.ts\" region=\"setup\" header=\"app/twain/twain.component.spec.ts (setup)\">\nbeforeEach(() => {\n testQuote = 'Test Quote';\n\n // Create a fake TwainService object with a `getQuote()` spy\n const twainService = jasmine.createSpyObj('TwainService', ['getQuote']);\n // Make the spy return a synchronous Observable with the test data\n getQuoteSpy = twainService.getQuote.and.returnValue(of(testQuote));\n\n TestBed.configureTestingModule({\n declarations: [TwainComponent],\n providers: [{provide: TwainService, useValue: twainService}]\n });\n\n fixture = TestBed.createComponent(TwainComponent);\n component = fixture.componentInstance;\n quoteEl = fixture.nativeElement.querySelector('.twain');\n});\n\n</code-example>\n<a id=\"service-spy\"></a>\n<p>Focus on the spy.</p>\n<code-example path=\"testing/src/app/twain/twain.component.spec.ts\" region=\"spy\">\n// Create a fake TwainService object with a `getQuote()` spy\nconst twainService = jasmine.createSpyObj('TwainService', ['getQuote']);\n// Make the spy return a synchronous Observable with the test data\ngetQuoteSpy = twainService.getQuote.and.returnValue(of(testQuote));\n\n</code-example>\n<p>The spy is designed such that any call to <code>getQuote</code> receives an observable with a test quote.\nUnlike the real <code>getQuote()</code> method, this spy bypasses the server\nand returns a synchronous observable whose value is available immediately.</p>\n<p>You can write many useful tests with this spy, even though its <code>Observable</code> is synchronous.</p>\n<a id=\"sync-tests\"></a>\n<h4 id=\"synchronous-tests\">Synchronous tests<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#synchronous-tests\"><i class=\"material-icons\">link</i></a></h4>\n<p>A key advantage of a synchronous <code>Observable</code> is that\nyou can often turn asynchronous processes into synchronous tests.</p>\n<code-example path=\"testing/src/app/twain/twain.component.spec.ts\" region=\"sync-test\">\nit('should show quote after component initialized', () => {\n fixture.detectChanges(); // onInit()\n\n // sync spy result shows testQuote immediately after init\n expect(quoteEl.textContent).toBe(testQuote);\n expect(getQuoteSpy.calls.any()).toBe(true, 'getQuote called');\n});\n\n</code-example>\n<p>Because the spy result returns synchronously, the <code>getQuote()</code> method updates\nthe message on screen immediately <em>after</em>\nthe first change detection cycle during which Angular calls <code>ngOnInit</code>.</p>\n<p>You're not so lucky when testing the error path.\nAlthough the service spy will return an error synchronously,\nthe component method calls <code>setTimeout()</code>.\nThe test must wait at least one full turn of the JavaScript engine before the\nvalue becomes available. The test must become <em>asynchronous</em>.</p>\n<a id=\"fake-async\"></a>\n<h4 id=\"async-test-with-fakeasync\">Async test with <em>fakeAsync()</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#async-test-with-fakeasync\"><i class=\"material-icons\">link</i></a></h4>\n<p>To use <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> functionality, you must import <code>zone.js/testing</code> in your test setup file.\nIf you created your project with the Angular CLI, <code>zone-testing</code> is already imported in <code>src/test.ts</code>.</p>\n<p>The following test confirms the expected behavior when the service returns an <code>ErrorObservable</code>.</p>\n<code-example path=\"testing/src/app/twain/twain.component.spec.ts\" region=\"error-test\">\nit('should display error when TwainService fails', <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n // tell spy to return an error observable\n getQuoteSpy.and.returnValue(throwError('TwainService test failure'));\n\n fixture.detectChanges(); // onInit()\n // sync spy errors immediately after init\n\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(); // <a href=\"api/core/testing/flush\" class=\"code-anchor\">flush</a> the component's setTimeout()\n\n fixture.detectChanges(); // update errorMessage within setTimeout()\n\n expect(errorMessage()).toMatch(/test failure/, 'should display error');\n expect(quoteEl.textContent).toBe('...', 'should show placeholder');\n }));\n\n</code-example>\n<p>Note that the <code>it()</code> function receives an argument of the following form.</p>\n<code-example language=\"javascript\">\n<a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => { /* test body */ })\n</code-example>\n<p>The <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> function enables a linear coding style by running the test body in a special <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a> test zone</code>.\nThe test body appears to be synchronous.\nThere is no nested syntax (like a <code>Promise.then()</code>) to disrupt the flow of control.</p>\n<div class=\"alert is-helpful\">\n<p>Limitation: The <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> function won't work if the test body makes an <code>XMLHttpRequest</code> (XHR) call.\nXHR calls within a test are rare, but if you need to call XHR, see <a href=\"guide/testing-components-scenarios#waitForAsync\"><code>waitForAsync()</code></a>, below.</p>\n</div>\n<a id=\"tick\"></a>\n<h4 id=\"the-tick-function\">The <em>tick()</em> function<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#the-tick-function\"><i class=\"material-icons\">link</i></a></h4>\n<p>You do have to call <a href=\"api/core/testing/tick\">tick()</a> to advance the (virtual) clock.</p>\n<p>Calling <a href=\"api/core/testing/tick\">tick()</a> simulates the passage of time until all pending asynchronous activities finish.\nIn this case, it waits for the error handler's <code>setTimeout()</code>.</p>\n<p>The <a href=\"api/core/testing/tick\">tick()</a> 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 <code>setTimeout(fn, 100)</code> in a <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> test, you need to use tick(100) to trigger the fn callback. The tickOptions is an optional parameter with a property called <code>processNewMacroTasksSynchronously</code> (defaults to true) that represents whether to invoke new generated macro tasks when ticking.</p>\n<code-example path=\"testing/src/app/demo/async-helper.spec.ts\" region=\"fake-async-test-tick\">\nit('should run timeout callback with delay after call <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a> with millis', <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n let called = false;\n setTimeout(() => {\n called = true;\n }, 100);\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(100);\n expect(called).toBe(true);\n }));\n\n</code-example>\n<p>The <a href=\"api/core/testing/tick\">tick()</a> function is one of the Angular testing utilities that you import with <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code>.\nIt's a companion to <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> and you can only call it within a <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> body.</p>\n<h4 id=\"tickoptions\">tickOptions<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#tickoptions\"><i class=\"material-icons\">link</i></a></h4>\n<code-example path=\"testing/src/app/demo/async-helper.spec.ts\" region=\"fake-async-test-tick-new-macro-task-sync\">\nit('should run new macro task callback with delay after call <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a> with millis',\n <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n function nestedTimer(cb: () => any): void {\n setTimeout(() => setTimeout(() => cb()));\n }\n const callback = jasmine.createSpy('callback');\n nestedTimer(callback);\n expect(callback).not.toHaveBeenCalled();\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(0);\n // the nested timeout will also be triggered\n expect(callback).toHaveBeenCalled();\n }));\n\n</code-example>\n<p>In this example, we have a new macro task (nested setTimeout), by default, when we <code><a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a></code>, the setTimeout <code>outside</code> and <code>nested</code> will both be triggered.</p>\n<code-example path=\"testing/src/app/demo/async-helper.spec.ts\" region=\"fake-async-test-tick-new-macro-task-async\">\nit('should not run new macro task callback with delay after call <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a> with millis',\n <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n function nestedTimer(cb: () => any): void {\n setTimeout(() => setTimeout(() => cb()));\n }\n const callback = jasmine.createSpy('callback');\n nestedTimer(callback);\n expect(callback).not.toHaveBeenCalled();\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(0, {processNewMacroTasksSynchronously: false});\n // the nested timeout will not be triggered\n expect(callback).not.toHaveBeenCalled();\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(0);\n expect(callback).toHaveBeenCalled();\n }));\n\n</code-example>\n<p>And in some case, we don't want to trigger the new macro task when ticking, we can use <code><a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(milliseconds, {processNewMacroTasksSynchronously: false})</code> to not invoke new macro task.</p>\n<h4 id=\"comparing-dates-inside-fakeasync\">Comparing dates inside fakeAsync()<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#comparing-dates-inside-fakeasync\"><i class=\"material-icons\">link</i></a></h4>\n<p><code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> simulates passage of time, which allows you to calculate the difference between dates inside <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code>.</p>\n<code-example path=\"testing/src/app/demo/async-helper.spec.ts\" region=\"fake-async-test-date\">\nit('should get Date diff correctly in <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>', <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n const start = Date.now();\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(100);\n const end = Date.now();\n expect(end - start).toBe(100);\n }));\n\n</code-example>\n<h4 id=\"jasmineclock-with-fakeasync\">jasmine.clock with fakeAsync()<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#jasmineclock-with-fakeasync\"><i class=\"material-icons\">link</i></a></h4>\n<p>Jasmine also provides a <code>clock</code> feature to mock dates. Angular automatically runs tests that are run after\n<code>jasmine.clock().install()</code> is called inside a <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> method until <code>jasmine.clock().uninstall()</code> is called. <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> is not needed and throws an error if nested.</p>\n<p>By default, this feature is disabled. To enable it, set a global flag before importing <code>zone-testing</code>.</p>\n<p>If you use the Angular CLI, configure this flag in <code>src/test.ts</code>.</p>\n<code-example>\n(window as any)['__zone_symbol__fakeAsyncPatchLock'] = true;\nimport 'zone.js/testing';\n</code-example>\n<code-example path=\"testing/src/app/demo/async-helper.spec.ts\" region=\"fake-async-test-clock\">\ndescribe('use jasmine.clock()', () => {\n // need to config __zone_symbol__fakeAsyncPatchLock flag\n // before loading zone.js/testing\n beforeEach(() => {\n jasmine.clock().install();\n });\n afterEach(() => {\n jasmine.clock().uninstall();\n });\n it('should auto enter <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>', () => {\n // is in <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a> now, don't need to call <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(testFn)\n let called = false;\n setTimeout(() => {\n called = true;\n }, 100);\n jasmine.clock().tick(100);\n expect(called).toBe(true);\n });\n});\n\n</code-example>\n<h4 id=\"using-the-rxjs-scheduler-inside-fakeasync\">Using the RxJS scheduler inside fakeAsync()<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#using-the-rxjs-scheduler-inside-fakeasync\"><i class=\"material-icons\">link</i></a></h4>\n<p>You can also use RxJS scheduler in <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> just like using <code>setTimeout()</code> or <code>setInterval()</code>, but you need to import <code>zone.js/plugins/zone-patch-rxjs-fake-async</code> to patch RxJS scheduler.\n<code-example path=\"testing/src/app/demo/async-helper.spec.ts\" region=\"fake-async-test-rxjs\">\nit('should get Date diff correctly in <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a> with rxjs scheduler', <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n // need to add `import 'zone.js/plugins/zone-patch-rxjs-fake-async'\n // to patch rxjs scheduler\n let result = null;\n of('hello').pipe(delay(1000)).subscribe(v => {\n result = v;\n });\n expect(result).toBeNull();\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(1000);\n expect(result).toBe('hello');\n\n const start = new Date().getTime();\n let dateDiff = 0;\n interval(1000).pipe(take(2)).subscribe(() => dateDiff = (new Date().getTime() - start));\n\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(1000);\n expect(dateDiff).toBe(1000);\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(1000);\n expect(dateDiff).toBe(2000);\n }));\n\n</code-example></p>\n<h4 id=\"support-more-macrotasks\">Support more macroTasks<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#support-more-macrotasks\"><i class=\"material-icons\">link</i></a></h4>\n<p>By default, <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> supports the following macro tasks.</p>\n<ul>\n<li><code>setTimeout</code></li>\n<li><code>setInterval</code></li>\n<li><code>requestAnimationFrame</code></li>\n<li><code>webkitRequestAnimationFrame</code></li>\n<li><code>mozRequestAnimationFrame</code></li>\n</ul>\n<p>If you run other macro tasks such as <code>HTMLCanvasElement.toBlob()</code>, an <em>\"Unknown macroTask scheduled in fake async test\"</em> error will be thrown.</p>\n<code-tabs>\n <code-pane header=\"src/app/shared/canvas.component.spec.ts (failing)\" path=\"testing/src/app/shared/canvas.component.spec.ts\" region=\"without-toBlob-macrotask\">\nimport { <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>, <a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>, <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>, <a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a> } from '@angular/core/testing';\n\nimport { CanvasComponent } from './canvas.component';\n\ndescribe('CanvasComponent', () => {\n beforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n <a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n declarations: [CanvasComponent],\n })\n .compileComponents();\n }));\n\n it('should be able to generate blob data from canvas', <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n const fixture = TestBed.createComponent(CanvasComponent);\n const canvasComp = fixture.componentInstance;\n\n fixture.detectChanges();\n expect(canvasComp.blobSize).toBe(0);\n\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>();\n expect(canvasComp.blobSize).toBeGreaterThan(0);\n }));\n});\n\n</code-pane>\n <code-pane header=\"src/app/shared/canvas.component.ts\" path=\"testing/src/app/shared/canvas.component.ts\" region=\"main\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a>, <a href=\"api/core/AfterViewInit\" class=\"code-anchor\">AfterViewInit</a>, <a href=\"api/core/ViewChild\" class=\"code-anchor\">ViewChild</a>, <a href=\"api/core/ElementRef\" class=\"code-anchor\">ElementRef</a> } from '@angular/core';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'sample-canvas',\n template: '&#x3C;canvas #sampleCanvas width=\"200\" height=\"200\">&#x3C;/canvas>',\n})\nexport class CanvasComponent implements <a href=\"api/core/AfterViewInit\" class=\"code-anchor\">AfterViewInit</a> {\n blobSize = 0;\n @<a href=\"api/core/ViewChild\" class=\"code-anchor\">ViewChild</a>('sampleCanvas') sampleCanvas: <a href=\"api/core/ElementRef\" class=\"code-anchor\">ElementRef</a>;\n\n ngAfterViewInit() {\n const canvas: HTMLCanvasElement = this.sampleCanvas.nativeElement;\n const context = canvas.getContext('2d');\n\n context.clearRect(0, 0, 200, 200);\n context.fillStyle = '#FF1122';\n context.fillRect(0, 0, 200, 200);\n\n canvas.toBlob(blob => {\n this.blobSize = blob.size;\n });\n }\n}\n\n</code-pane>\n</code-tabs>\n<p>If you want to support such a case, you need to define the macro task you want to support in <code>beforeEach()</code>.\nFor example:</p>\n<code-example header=\"src/app/shared/canvas.component.spec.ts (excerpt)\" path=\"testing/src/app/shared/canvas.component.spec.ts\" region=\"enable-toBlob-macrotask\">\nbeforeEach(() => {\n (window as any).__zone_symbol__FakeAsyncTestMacroTask = [\n {\n source: 'HTMLCanvasElement.toBlob',\n callbackArgs: [{size: 200}],\n },\n ];\n});\n\n</code-example>\n<p>Note that in order to make the <code>&#x3C;canvas></code> element Zone.js-aware in your app, you need to import the <code>zone-patch-canvas</code> patch (either in <code>polyfills.ts</code> or in the specific file that uses <code>&#x3C;canvas></code>):</p>\n<code-example header=\"src/polyfills.ts or src/app/shared/canvas.component.ts\" path=\"testing/src/app/shared/canvas.component.ts\" region=\"import-canvas-patch\">\n// Import patch to make async `HTMLCanvasElement` methods (such as `.toBlob()`) Zone.js-aware.\n// Either import in `polyfills.ts` (if used in more than one places in the app) or in the component\n// file using `HTMLCanvasElement` (if it is only used in a single file).\nimport 'zone.js/plugins/zone-patch-canvas';\n\n</code-example>\n<h4 id=\"async-observables\">Async observables<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#async-observables\"><i class=\"material-icons\">link</i></a></h4>\n<p>You might be satisfied with the test coverage of these tests.</p>\n<p>However, you might be troubled by the fact that the real service doesn't quite behave this way.\nThe real service sends requests to a remote server.\nA server takes time to respond and the response certainly won't be available immediately\nas in the previous two tests.</p>\n<p>Your tests will reflect the real world more faithfully if you return an <em>asynchronous</em> observable\nfrom the <code>getQuote()</code> spy like this.</p>\n<code-example path=\"testing/src/app/twain/twain.component.spec.ts\" region=\"async-setup\">\n// Simulate delayed observable values with the `asyncData()` helper\ngetQuoteSpy.and.returnValue(asyncData(testQuote));\n\n</code-example>\n<h4 id=\"async-observable-helpers\">Async observable helpers<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#async-observable-helpers\"><i class=\"material-icons\">link</i></a></h4>\n<p>The async observable was produced by an <code>asyncData</code> helper.\nThe <code>asyncData</code> helper is a utility function that you'll have to write yourself, or you can copy this one from the sample code.</p>\n<code-example path=\"testing/src/testing/async-observable-helpers.ts\" region=\"async-data\" header=\"testing/async-observable-helpers.ts\">\n/**\n * Create async observable that emits-once and completes\n * after a JS engine turn\n */\nexport function asyncData&#x3C;T>(data: T) {\n return defer(() => Promise.resolve(data));\n}\n\n</code-example>\n<p>This helper's observable emits the <code>data</code> value in the next turn of the JavaScript engine.</p>\n<p>The <a href=\"http://reactivex.io/documentation/operators/defer.html\">RxJS <code>defer()</code> operator</a> returns an observable.\nIt takes a factory function that returns either a promise or an observable.\nWhen something subscribes to <em>defer</em>'s observable,\nit adds the subscriber to a new observable created with that factory.</p>\n<p>The <code>defer()</code> operator transforms the <code>Promise.resolve()</code> into a new observable that,\nlike <code><a href=\"api/common/http/HttpClient\" class=\"code-anchor\">HttpClient</a></code>, emits once and completes.\nSubscribers are unsubscribed after they receive the data value.</p>\n<p>There's a similar helper for producing an async error.</p>\n<code-example path=\"testing/src/testing/async-observable-helpers.ts\" region=\"async-error\">\n/**\n * Create async observable error that errors\n * after a JS engine turn\n */\nexport function asyncError&#x3C;T>(errorObject: any) {\n return defer(() => Promise.reject(errorObject));\n}\n\n</code-example>\n<h4 id=\"more-async-tests\">More async tests<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#more-async-tests\"><i class=\"material-icons\">link</i></a></h4>\n<p>Now that the <code>getQuote()</code> spy is returning async observables,\nmost of your tests will have to be async as well.</p>\n<p>Here's a <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> test that demonstrates the data flow you'd expect\nin the real world.</p>\n<code-example path=\"testing/src/app/twain/twain.component.spec.ts\" region=\"fake-async-test\">\nit('should show quote after getQuote (<a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>)', <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n fixture.detectChanges(); // ngOnInit()\n expect(quoteEl.textContent).toBe('...', 'should show placeholder');\n\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(); // <a href=\"api/core/testing/flush\" class=\"code-anchor\">flush</a> the observable to get the quote\n fixture.detectChanges(); // update view\n\n expect(quoteEl.textContent).toBe(testQuote, 'should show quote');\n expect(errorMessage()).toBeNull('should not show error');\n }));\n\n</code-example>\n<p>Notice that the quote element displays the placeholder value (<code>'...'</code>) after <code>ngOnInit()</code>.\nThe first quote hasn't arrived yet.</p>\n<p>To flush the first quote from the observable, you call <a href=\"api/core/testing/tick\">tick()</a>.\nThen call <code>detectChanges()</code> to tell Angular to update the screen.</p>\n<p>Then you can assert that the quote element displays the expected text.</p>\n<a id=\"waitForAsync\"></a>\n<h4 id=\"async-test-with-waitforasync\">Async test with <em>waitForAsync()</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#async-test-with-waitforasync\"><i class=\"material-icons\">link</i></a></h4>\n<p>To use <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> functionality, you must import <code>zone.js/testing</code> in your test setup file.\nIf you created your project with the Angular CLI, <code>zone-testing</code> is already imported in <code>src/test.ts</code>.</p>\n<div class=\"alert is-helpful\">\n<p>The <code>TestBed.compileComponents()</code> method (see <a href=\"guide/testing-components-scenarios#compile-components\">below</a>) calls <code>XHR</code>\nto read external template and css files during \"just-in-time\" compilation.\nWrite tests that call <code>compileComponents()</code> with the <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> utility.</p>\n</div>\n<p>Here's the previous <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> test, re-written with the <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> utility.</p>\n<code-example path=\"testing/src/app/twain/twain.component.spec.ts\" region=\"async-test\">\nit('should show quote after getQuote (async)', <a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n fixture.detectChanges(); // ngOnInit()\n expect(quoteEl.textContent).toBe('...', 'should show placeholder');\n\n fixture.whenStable().then(() => { // wait for async getQuote\n fixture.detectChanges(); // update view with quote\n expect(quoteEl.textContent).toBe(testQuote);\n expect(errorMessage()).toBeNull('should not show error');\n });\n }));\n\n</code-example>\n<p>The <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> utility hides some asynchronous boilerplate by arranging for the tester's code\nto run in a special <em>async test zone</em>.\nYou don't need to pass Jasmine's <code>done()</code> into the test and call <code>done()</code> because it is <code>undefined</code> in promise or observable callbacks.</p>\n<p>But the test's asynchronous nature is revealed by the call to <code>fixture.whenStable()</code>,\nwhich breaks the linear flow of control.</p>\n<p>When using an <code>intervalTimer()</code> such as <code>setInterval()</code> in <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code>, remember to cancel the timer with <code>clearInterval()</code> after the test, otherwise the <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> never ends.</p>\n<a id=\"when-stable\"></a>\n<h4 id=\"whenstable\"><em>whenStable</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#whenstable\"><i class=\"material-icons\">link</i></a></h4>\n<p>The test must wait for the <code>getQuote()</code> observable to emit the next quote.\nInstead of calling <a href=\"api/core/testing/tick\">tick()</a>, it calls <code>fixture.whenStable()</code>.</p>\n<p>The <code>fixture.whenStable()</code> returns a promise that resolves when the JavaScript engine's\ntask queue becomes empty.\nIn this example, the task queue becomes empty when the observable emits the first quote.</p>\n<p>The test resumes within the promise callback, which calls <code>detectChanges()</code> to\nupdate the quote element with the expected text.</p>\n<a id=\"jasmine-done\"></a>\n<h4 id=\"jasmine-done\">Jasmine <em>done()</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#jasmine-done\"><i class=\"material-icons\">link</i></a></h4>\n<p>While the <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> and <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> functions greatly\nsimplify Angular asynchronous testing,\nyou can still fall back to the traditional technique\nand pass <code>it</code> a function that takes a\n<a href=\"https://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support\"><code>done</code> callback</a>.</p>\n<p>You can't call <code>done()</code> in <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> or <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> functions, because the <code>done parameter</code>\nis <code>undefined</code>.</p>\n<p>Now you are responsible for chaining promises, handling errors, and calling <code>done()</code> at the appropriate moments.</p>\n<p>Writing test functions with <code>done()</code>, is more cumbersome than <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code>and <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code>, but it is occasionally necessary when code involves the <code>intervalTimer()</code> like <code>setInterval</code>.</p>\n<p>Here are two more versions of the previous test, written with <code>done()</code>.\nThe first one subscribes to the <code>Observable</code> exposed to the template by the component's <code>quote</code> property.</p>\n<code-example path=\"testing/src/app/twain/twain.component.spec.ts\" region=\"quote-done-test\">\nit('should show last quote (quote done)', (done: DoneFn) => {\n fixture.detectChanges();\n\n component.quote.pipe(last()).subscribe(() => {\n fixture.detectChanges(); // update view with quote\n expect(quoteEl.textContent).toBe(testQuote);\n expect(errorMessage()).toBeNull('should not show error');\n done();\n });\n});\n\n</code-example>\n<p>The RxJS <code>last()</code> operator emits the observable's last value before completing, which will be the test quote.\nThe <code>subscribe</code> callback calls <code>detectChanges()</code> to\nupdate the quote element with the test quote, in the same manner as the earlier tests.</p>\n<p>In some tests, you're more interested in how an injected service method was called and what values it returned,\nthan what appears on screen.</p>\n<p>A service spy, such as the <code>qetQuote()</code> spy of the fake <code>TwainService</code>,\ncan give you that information and make assertions about the state of the view.</p>\n<code-example path=\"testing/src/app/twain/twain.component.spec.ts\" region=\"spy-done-test\">\nit('should show quote after getQuote (spy done)', (done: DoneFn) => {\n fixture.detectChanges();\n\n // the spy's most recent call returns the observable with the test quote\n getQuoteSpy.calls.mostRecent().returnValue.subscribe(() => {\n fixture.detectChanges(); // update view with quote\n expect(quoteEl.textContent).toBe(testQuote);\n expect(errorMessage()).toBeNull('should not show error');\n done();\n });\n});\n\n</code-example>\n<a id=\"marble-testing\"></a>\n<h2 id=\"component-marble-tests\">Component marble tests<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#component-marble-tests\"><i class=\"material-icons\">link</i></a></h2>\n<p>The previous <code>TwainComponent</code> tests simulated an asynchronous observable response\nfrom the <code>TwainService</code> with the <code>asyncData</code> and <code>asyncError</code> utilities.</p>\n<p>These are short, simple functions that you can write yourself.\nUnfortunately, they're too simple for many common scenarios.\nAn observable often emits multiple times, perhaps after a significant delay.\nA component may coordinate multiple observables\nwith overlapping sequences of values and errors.</p>\n<p><strong>RxJS marble testing</strong> is a great way to test observable scenarios,\nboth simple and complex.\nYou've likely seen the <a href=\"https://rxmarbles.com/\">marble diagrams</a>\nthat illustrate how observables work.\nMarble testing uses a similar marble language to\nspecify the observable streams and expectations in your tests.</p>\n<p>The following examples revisit two of the <code>TwainComponent</code> tests\nwith marble testing.</p>\n<p>Start by installing the <code>jasmine-marbles</code> npm package.\nThen import the symbols you need.</p>\n<code-example path=\"testing/src/app/twain/twain.component.marbles.spec.ts\" region=\"import-marbles\" header=\"app/twain/twain.component.marbles.spec.ts (import marbles)\">\nimport { cold, getTestScheduler } from 'jasmine-marbles';\n\n</code-example>\n<p>Here's the complete test for getting a quote:</p>\n<code-example path=\"testing/src/app/twain/twain.component.marbles.spec.ts\" region=\"get-quote-test\">\nit('should show quote after getQuote (marbles)', () => {\n // observable test quote value and complete(), after delay\n const q$ = cold('---x|', { x: testQuote });\n getQuoteSpy.and.returnValue( q$ );\n\n fixture.detectChanges(); // ngOnInit()\n expect(quoteEl.textContent).toBe('...', 'should show placeholder');\n\n getTestScheduler().flush(); // <a href=\"api/core/testing/flush\" class=\"code-anchor\">flush</a> the observables\n\n fixture.detectChanges(); // update view\n\n expect(quoteEl.textContent).toBe(testQuote, 'should show quote');\n expect(errorMessage()).toBeNull('should not show error');\n});\n\n</code-example>\n<p>Notice that the Jasmine test is synchronous. There's no <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code>.\nMarble testing uses a test scheduler to simulate the passage of time\nin a synchronous test.</p>\n<p>The beauty of marble testing is in the visual definition of the observable streams.\nThis test defines a <a href=\"guide/testing-components-scenarios#cold-observable\"><em>cold</em> observable</a> that waits\nthree <a href=\"guide/testing-components-scenarios#marble-frame\">frames</a> (<code>---</code>),\nemits a value (<code>x</code>), and completes (<code>|</code>).\nIn the second argument you map the value marker (<code>x</code>) to the emitted value (<code>testQuote</code>).</p>\n<code-example path=\"testing/src/app/twain/twain.component.marbles.spec.ts\" region=\"test-quote-marbles\">\nconst q$ = cold('---x|', { x: testQuote });\n\n</code-example>\n<p>The marble library constructs the corresponding observable, which the\ntest sets as the <code>getQuote</code> spy's return value.</p>\n<p>When you're ready to activate the marble observables,\nyou tell the <code>TestScheduler</code> to <em>flush</em> its queue of prepared tasks like this.</p>\n<code-example path=\"testing/src/app/twain/twain.component.marbles.spec.ts\" region=\"test-scheduler-flush\">\ngetTestScheduler().flush(); // <a href=\"api/core/testing/flush\" class=\"code-anchor\">flush</a> the observables\n\n</code-example>\n<p>This step serves a purpose analogous to <a href=\"api/core/testing/tick\">tick()</a> and <code>whenStable()</code> in the\nearlier <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> and <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> examples.\nThe balance of the test is the same as those examples.</p>\n<h4 id=\"marble-error-testing\">Marble error testing<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#marble-error-testing\"><i class=\"material-icons\">link</i></a></h4>\n<p>Here's the marble testing version of the <code>getQuote()</code> error test.</p>\n<code-example path=\"testing/src/app/twain/twain.component.marbles.spec.ts\" region=\"error-test\">\nit('should display error when TwainService fails', <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n // observable error after delay\n const q$ = cold('---#|', null, new Error('TwainService test failure'));\n getQuoteSpy.and.returnValue( q$ );\n\n fixture.detectChanges(); // ngOnInit()\n expect(quoteEl.textContent).toBe('...', 'should show placeholder');\n\n getTestScheduler().flush(); // <a href=\"api/core/testing/flush\" class=\"code-anchor\">flush</a> the observables\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(); // component shows error after a setTimeout()\n fixture.detectChanges(); // update error message\n\n expect(errorMessage()).toMatch(/test failure/, 'should display error');\n expect(quoteEl.textContent).toBe('...', 'should show placeholder');\n}));\n\n</code-example>\n<p>It's still an async test, calling <code><a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>()</code> and <a href=\"api/core/testing/tick\">tick()</a>, because the component itself\ncalls <code>setTimeout()</code> when processing errors.</p>\n<p>Look at the marble observable definition.</p>\n<code-example path=\"testing/src/app/twain/twain.component.marbles.spec.ts\" region=\"error-marbles\">\nconst q$ = cold('---#|', null, new Error('TwainService test failure'));\n\n</code-example>\n<p>This is a <em>cold</em> observable that waits three frames and then emits an error,\nThe hash (<code>#</code>) indicates the timing of the error that is specified in the third argument.\nThe second argument is null because the observable never emits a value.</p>\n<h4 id=\"learn-about-marble-testing\">Learn about marble testing<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#learn-about-marble-testing\"><i class=\"material-icons\">link</i></a></h4>\n<a id=\"marble-frame\"></a>\n<p>A <em>marble frame</em> is a virtual unit of testing time.\nEach symbol (<code>-</code>, <code>x</code>, <code>|</code>, <code>#</code>) marks the passing of one frame.</p>\n<a id=\"cold-observable\"></a>\n<p>A <em>cold</em> observable doesn't produce values until you subscribe to it.\nMost of your application observables are cold.\nAll <a href=\"guide/http\"><em>HttpClient</em></a> methods return cold observables.</p>\n<p>A <em>hot</em> observable is already producing values <em>before</em> you subscribe to it.\nThe <a href=\"api/router/Router#events\"><em>Router.events</em></a> observable,\nwhich reports router activity, is a <em>hot</em> observable.</p>\n<p>RxJS marble testing is a rich subject, beyond the scope of this guide.\nLearn about it on the web, starting with the\n<a href=\"https://rxjs.dev/guide/testing/marble-testing\">official documentation</a>.</p>\n<a id=\"component-with-input-output\"></a>\n<h2 id=\"component-with-inputs-and-outputs\">Component with inputs and outputs<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#component-with-inputs-and-outputs\"><i class=\"material-icons\">link</i></a></h2>\n<p>A component with inputs and outputs typically appears inside the view template of a host component.\nThe host uses a property binding to set the input property and an event binding to\nlisten to events raised by the output property.</p>\n<p>The testing goal is to verify that such bindings work as expected.\nThe tests should set input values and listen for output events.</p>\n<p>The <code>DashboardHeroComponent</code> is a tiny example of a component in this role.\nIt displays an individual hero provided by the <code>DashboardComponent</code>.\nClicking that hero tells the <code>DashboardComponent</code> that the user has selected the hero.</p>\n<p>The <code>DashboardHeroComponent</code> is embedded in the <code>DashboardComponent</code> template like this:</p>\n<code-example path=\"testing/src/app/dashboard/dashboard.component.html\" region=\"dashboard-hero\" header=\"app/dashboard/dashboard.component.html (excerpt)\">\n&#x3C;dashboard-hero *<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a>=\"let hero of heroes\" class=\"col-1-4\"\n [hero]=hero (selected)=\"gotoDetail($event)\" >\n&#x3C;/dashboard-hero>\n\n</code-example>\n<p>The <code>DashboardHeroComponent</code> appears in an <code>*<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a></code> repeater, which sets each component's <code>hero</code> input property\nto the looping value and listens for the component's <code>selected</code> event.</p>\n<p>Here's the component's full definition:</p>\n<a id=\"dashboard-hero-component\"></a>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.ts\" region=\"component\" header=\"app/dashboard/dashboard-hero.component.ts (component)\">\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'dashboard-hero',\n template: `\n &#x3C;div (click)=\"click()\" class=\"hero\">\n {{hero.name | <a href=\"api/common/UpperCasePipe\" class=\"code-anchor\">uppercase</a>}}\n &#x3C;/div>`,\n styleUrls: [ './dashboard-hero.component.css' ]\n})\nexport class DashboardHeroComponent {\n @<a href=\"api/core/Input\" class=\"code-anchor\">Input</a>() hero: Hero;\n @<a href=\"api/core/Output\" class=\"code-anchor\">Output</a>() selected = new <a href=\"api/core/EventEmitter\" class=\"code-anchor\">EventEmitter</a>&#x3C;Hero>();\n click() { this.selected.emit(this.hero); }\n}\n\n</code-example>\n<p>While testing a component this simple has little intrinsic value, it's worth knowing how.\nYou can use one of these approaches:</p>\n<ul>\n<li>Test it as used by <code>DashboardComponent</code>.</li>\n<li>Test it as a stand-alone component.</li>\n<li>Test it as used by a substitute for <code>DashboardComponent</code>.</li>\n</ul>\n<p>A quick look at the <code>DashboardComponent</code> constructor discourages the first approach:</p>\n<code-example path=\"testing/src/app/dashboard/dashboard.component.ts\" region=\"ctor\" header=\"app/dashboard/dashboard.component.ts (constructor)\">\nconstructor(\n private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>,\n private heroService: HeroService) {\n}\n\n</code-example>\n<p>The <code>DashboardComponent</code> depends on the Angular router and the <code>HeroService</code>.\nYou'd probably have to replace them both with test doubles, which is a lot of work.\nThe router seems particularly challenging.</p>\n<div class=\"alert is-helpful\">\n<p>The <a href=\"guide/testing-components-scenarios#routing-component\">discussion below</a> covers testing components that require the router.</p>\n</div>\n<p>The immediate goal is to test the <code>DashboardHeroComponent</code>, not the <code>DashboardComponent</code>,\nso, try the second and third options.</p>\n<a id=\"dashboard-standalone\"></a>\n<h4 id=\"test-dashboardherocomponent-stand-alone\">Test <em>DashboardHeroComponent</em> stand-alone<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#test-dashboardherocomponent-stand-alone\"><i class=\"material-icons\">link</i></a></h4>\n<p>Here's the meat of the spec file setup.</p>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.spec.ts\" region=\"setup\" header=\"app/dashboard/dashboard-hero.component.spec.ts (setup)\">\n<a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({declarations: [DashboardHeroComponent]})\nfixture = TestBed.createComponent(DashboardHeroComponent);\ncomp = fixture.componentInstance;\n\n// find the hero's <a href=\"api/core/DebugElement\" class=\"code-anchor\">DebugElement</a> and element\nheroDe = fixture.debugElement.query(By.css('.hero'));\nheroEl = heroDe.nativeElement;\n\n// mock the hero supplied by the parent component\nexpectedHero = {id: 42, name: 'Test Name'};\n\n// simulate the parent setting the input property with that hero\ncomp.hero = expectedHero;\n\n// <a href=\"api/animations/trigger\" class=\"code-anchor\">trigger</a> initial data binding\nfixture.detectChanges();\n\n</code-example>\n<p>Note how the setup code assigns a test hero (<code>expectedHero</code>) to the component's <code>hero</code> property,\nemulating the way the <code>DashboardComponent</code> would set it\nvia the property binding in its repeater.</p>\n<p>The following test verifies that the hero name is propagated to the template via a binding.</p>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.spec.ts\" region=\"name-test\">\nit('should display hero name in uppercase', () => {\n const expectedPipedName = expectedHero.name.toUpperCase();\n expect(heroEl.textContent).toContain(expectedPipedName);\n});\n\n</code-example>\n<p>Because the <a href=\"guide/testing-components-scenarios#dashboard-hero-component\">template</a> passes the hero name through the Angular <code><a href=\"api/common/UpperCasePipe\" class=\"code-anchor\">UpperCasePipe</a></code>,\nthe test must match the element value with the upper-cased name.</p>\n<div class=\"alert is-helpful\">\n<p>This small test demonstrates how Angular tests can verify a component's visual\nrepresentation—something not possible with\n<a href=\"guide/testing-components-basics#component-class-testing\">component class tests</a>—at\nlow cost and without resorting to much slower and more complicated end-to-end tests.</p>\n</div>\n<h4 id=\"clicking\">Clicking<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#clicking\"><i class=\"material-icons\">link</i></a></h4>\n<p>Clicking the hero should raise a <code>selected</code> event that\nthe host component (<code>DashboardComponent</code> presumably) can hear:</p>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.spec.ts\" region=\"click-test\">\nit('should raise selected event when clicked (triggerEventHandler)', () => {\n let selectedHero: Hero;\n comp.selected.subscribe((hero: Hero) => selectedHero = hero);\n\n heroDe.triggerEventHandler('click', null);\n expect(selectedHero).toBe(expectedHero);\n});\n\n</code-example>\n<p>The component's <code>selected</code> property returns an <code><a href=\"api/core/EventEmitter\" class=\"code-anchor\">EventEmitter</a></code>,\nwhich looks like an RxJS synchronous <code>Observable</code> to consumers.\nThe test subscribes to it <em>explicitly</em> just as the host component does <em>implicitly</em>.</p>\n<p>If the component behaves as expected, clicking the hero's element\nshould tell the component's <code>selected</code> property to emit the <code>hero</code> object.</p>\n<p>The test detects that event through its subscription to <code>selected</code>.</p>\n<a id=\"trigger-event-handler\"></a>\n<h4 id=\"triggereventhandler\"><em>triggerEventHandler</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#triggereventhandler\"><i class=\"material-icons\">link</i></a></h4>\n<p>The <code>heroDe</code> in the previous test is a <code><a href=\"api/core/DebugElement\" class=\"code-anchor\">DebugElement</a></code> that represents the hero <code>&#x3C;div></code>.</p>\n<p>It has Angular properties and methods that abstract interaction with the native element.\nThis test calls the <code>DebugElement.triggerEventHandler</code> with the \"click\" event name.\nThe \"click\" event binding responds by calling <code>DashboardHeroComponent.click()</code>.</p>\n<p>The Angular <code>DebugElement.triggerEventHandler</code> can raise <em>any data-bound event</em> by its <em>event name</em>.\nThe second parameter is the event object passed to the handler.</p>\n<p>The test triggered a \"click\" event with a <code>null</code> event object.</p>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.spec.ts\" region=\"trigger-event-handler\">\nheroDe.triggerEventHandler('click', null);\n\n</code-example>\n<p>The test assumes (correctly in this case) that the runtime\nevent handler—the component's <code>click()</code> method—doesn't\ncare about the event object.</p>\n<div class=\"alert is-helpful\">\n<p>Other handlers are less forgiving. For example, the <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code>\ndirective expects an object with a <code>button</code> property\nthat identifies which mouse button (if any) was pressed during the click.\nThe <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> directive throws an error if the event object is missing.</p>\n</div>\n<h4 id=\"click-the-element\">Click the element<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#click-the-element\"><i class=\"material-icons\">link</i></a></h4>\n<p>The following test alternative calls the native element's own <code>click()</code> method,\nwhich is perfectly fine for <em>this component</em>.</p>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.spec.ts\" region=\"click-test-2\">\nit('should raise selected event when clicked (element.click)', () => {\n let selectedHero: Hero;\n comp.selected.subscribe((hero: Hero) => selectedHero = hero);\n\n heroEl.click();\n expect(selectedHero).toBe(expectedHero);\n});\n\n</code-example>\n<a id=\"click-helper\"></a>\n<h4 id=\"click-helper\"><em>click()</em> helper<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#click-helper\"><i class=\"material-icons\">link</i></a></h4>\n<p>Clicking a button, an anchor, or an arbitrary HTML element is a common test task.</p>\n<p>Make that consistent and easy by encapsulating the <em>click-triggering</em> process\nin a helper such as the <code>click()</code> function below:</p>\n<code-example path=\"testing/src/testing/index.ts\" region=\"click-event\" header=\"testing/index.ts (click helper)\">\n/** Button events to pass to `DebugElement.triggerEventHandler` for <a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a> event handler */\nexport const ButtonClickEvents = {\n left: { button: 0 },\n right: { button: 2 }\n};\n\n/** Simulate element click. Defaults to mouse left-button click event. */\nexport function click(el: <a href=\"api/core/DebugElement\" class=\"code-anchor\">DebugElement</a> | HTMLElement, eventObj: any = ButtonClickEvents.left): void {\n if (el instanceof HTMLElement) {\n el.click();\n } else {\n el.triggerEventHandler('click', eventObj);\n }\n}\n\n</code-example>\n<p>The first parameter is the <em>element-to-click</em>. If you wish, you can pass a\ncustom event object as the second parameter. The default is a (partial)\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button\">left-button mouse event object</a>\naccepted by many handlers including the <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> directive.</p>\n<div class=\"alert is-important\">\n<p>The <code>click()</code> helper function is <strong>not</strong> one of the Angular testing utilities.\nIt's a function defined in <em>this guide's sample code</em>.\nAll of the sample tests use it.\nIf you like it, add it to your own collection of helpers.</p>\n</div>\n<p>Here's the previous test, rewritten using the click helper.</p>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.spec.ts\" region=\"click-test-3\" header=\"app/dashboard/dashboard-hero.component.spec.ts (test with click helper)\">\nit('should raise selected event when clicked (click helper)', () => {\n let selectedHero: Hero;\n comp.selected.subscribe((hero: Hero) => selectedHero = hero);\n\n click(heroDe); // click helper with <a href=\"api/core/DebugElement\" class=\"code-anchor\">DebugElement</a>\n click(heroEl); // click helper with native element\n\n expect(selectedHero).toBe(expectedHero);\n});\n\n</code-example>\n<a id=\"component-inside-test-host\"></a>\n<h2 id=\"component-inside-a-test-host\">Component inside a test host<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#component-inside-a-test-host\"><i class=\"material-icons\">link</i></a></h2>\n<p>The previous tests played the role of the host <code>DashboardComponent</code> themselves.\nBut does the <code>DashboardHeroComponent</code> work correctly when properly data-bound to a host component?</p>\n<p>You could test with the actual <code>DashboardComponent</code>.\nBut doing so could require a lot of setup,\nespecially when its template features an <code>*<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a></code> repeater,\nother components, layout HTML, additional bindings,\na constructor that injects multiple services,\nand it starts interacting with those services right away.</p>\n<p>Imagine the effort to disable these distractions, just to prove a point\nthat can be made satisfactorily with a <em>test host</em> like this one:</p>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.spec.ts\" region=\"test-host\" header=\"app/dashboard/dashboard-hero.component.spec.ts (test host)\">\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n template: `\n &#x3C;dashboard-hero\n [hero]=\"hero\" (selected)=\"onSelected($event)\">\n &#x3C;/dashboard-hero>`\n})\nclass TestHostComponent {\n hero: Hero = {id: 42, name: 'Test Name'};\n selectedHero: Hero;\n onSelected(hero: Hero) {\n this.selectedHero = hero;\n }\n}\n\n</code-example>\n<p>This test host binds to <code>DashboardHeroComponent</code> as the <code>DashboardComponent</code> would\nbut without the noise of the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code>, the <code>HeroService</code>, or the <code>*<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a></code> repeater.</p>\n<p>The test host sets the component's <code>hero</code> input property with its test hero.\nIt binds the component's <code>selected</code> event with its <code>onSelected</code> handler,\nwhich records the emitted hero in its <code>selectedHero</code> property.</p>\n<p>Later, the tests will be able to easily check <code>selectedHero</code> to verify that the\n<code>DashboardHeroComponent.selected</code> event emitted the expected hero.</p>\n<p>The setup for the <em>test-host</em> tests is similar to the setup for the stand-alone tests:</p>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.spec.ts\" region=\"test-host-setup\" header=\"app/dashboard/dashboard-hero.component.spec.ts (test host setup)\">\n<a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({declarations: [DashboardHeroComponent, TestHostComponent]})\n// create TestHostComponent instead of DashboardHeroComponent\nfixture = TestBed.createComponent(TestHostComponent);\ntestHost = fixture.componentInstance;\nheroEl = fixture.nativeElement.querySelector('.hero');\nfixture.detectChanges(); // <a href=\"api/animations/trigger\" class=\"code-anchor\">trigger</a> initial data binding\n\n</code-example>\n<p>This testing module configuration shows three important differences:</p>\n<ol>\n<li>It <em>declares</em> both the <code>DashboardHeroComponent</code> and the <code>TestHostComponent</code>.</li>\n<li>It <em>creates</em> the <code>TestHostComponent</code> instead of the <code>DashboardHeroComponent</code>.</li>\n<li>The <code>TestHostComponent</code> sets the <code>DashboardHeroComponent.hero</code> with a binding.</li>\n</ol>\n<p>The <code>createComponent</code> returns a <code>fixture</code> that holds an instance of <code>TestHostComponent</code> instead of an instance of <code>DashboardHeroComponent</code>.</p>\n<p>Creating the <code>TestHostComponent</code> has the side-effect of creating a <code>DashboardHeroComponent</code>\nbecause the latter appears within the template of the former.\nThe query for the hero element (<code>heroEl</code>) still finds it in the test DOM,\nalbeit at greater depth in the element tree than before.</p>\n<p>The tests themselves are almost identical to the stand-alone version:</p>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.spec.ts\" region=\"test-host-tests\" header=\"app/dashboard/dashboard-hero.component.spec.ts (test-host)\">\nit('should display hero name', () => {\n const expectedPipedName = testHost.hero.name.toUpperCase();\n expect(heroEl.textContent).toContain(expectedPipedName);\n});\n\nit('should raise selected event when clicked', () => {\n click(heroEl);\n // selected hero should be the same data bound hero\n expect(testHost.selectedHero).toBe(testHost.hero);\n});\n\n</code-example>\n<p>Only the selected event test differs. It confirms that the selected <code>DashboardHeroComponent</code> hero\nreally does find its way up through the event binding to the host component.</p>\n<a id=\"routing-component\"></a>\n<h2 id=\"routing-component\">Routing component<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#routing-component\"><i class=\"material-icons\">link</i></a></h2>\n<p>A <em>routing component</em> is a component that tells the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> to navigate to another component.\nThe <code>DashboardComponent</code> is a <em>routing component</em> because the user can\nnavigate to the <code>HeroDetailComponent</code> by clicking on one of the <em>hero buttons</em> on the dashboard.</p>\n<p>Routing is pretty complicated.\nTesting the <code>DashboardComponent</code> seemed daunting in part because it involves the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code>,\nwhich it injects together with the <code>HeroService</code>.</p>\n<code-example path=\"testing/src/app/dashboard/dashboard.component.ts\" region=\"ctor\" header=\"app/dashboard/dashboard.component.ts (constructor)\">\nconstructor(\n private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>,\n private heroService: HeroService) {\n}\n\n</code-example>\n<p>Mocking the <code>HeroService</code> with a spy is a <a href=\"guide/testing-components-scenarios#component-with-async-service\">familiar story</a>.\nBut the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> has a complicated API and is entwined with other services and application preconditions. Might it be difficult to mock?</p>\n<p>Fortunately, not in this case because the <code>DashboardComponent</code> isn't doing much with the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code></p>\n<code-example path=\"testing/src/app/dashboard/dashboard.component.ts\" region=\"goto-detail\" header=\"app/dashboard/dashboard.component.ts (goToDetail)\">\ngotoDetail(hero: Hero) {\n const url = `/heroes/${hero.id}`;\n this.router.navigateByUrl(url);\n}\n\n</code-example>\n<p>This is often the case with <em>routing components</em>.\nAs a rule you test the component, not the router,\nand care only if the component navigates with the right address under the given conditions.</p>\n<p>Providing a router spy for <em>this component</em> test suite happens to be as easy\nas providing a <code>HeroService</code> spy.</p>\n<code-example path=\"testing/src/app/dashboard/dashboard.component.spec.ts\" region=\"router-spy\" header=\"app/dashboard/dashboard.component.spec.ts (spies)\">\nconst routerSpy = jasmine.createSpyObj('<a href=\"api/router/Router\" class=\"code-anchor\">Router</a>', ['navigateByUrl']);\nconst heroServiceSpy = jasmine.createSpyObj('HeroService', ['getHeroes']);\n\n<a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n providers: [\n {provide: HeroService, useValue: heroServiceSpy}, {provide: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>, useValue: routerSpy}\n ]\n })\n\n</code-example>\n<p>The following test clicks the displayed hero and confirms that\n<code>Router.navigateByUrl</code> is called with the expected url.</p>\n<code-example path=\"testing/src/app/dashboard/dashboard.component.spec.ts\" region=\"navigate-test\" header=\"app/dashboard/dashboard.component.spec.ts (navigate test)\">\nit('should tell ROUTER to navigate when hero clicked', () => {\n heroClick(); // <a href=\"api/animations/trigger\" class=\"code-anchor\">trigger</a> click on first inner &#x3C;div class=\"hero\">\n\n // args passed to router.navigateByUrl() spy\n const spy = router.navigateByUrl as jasmine.Spy;\n const navArgs = spy.calls.first().args[0];\n\n // expecting to navigate to id of the component's first hero\n const id = comp.heroes[0].id;\n expect(navArgs).toBe('/heroes/' + id, 'should nav to HeroDetail for first hero');\n});\n\n</code-example>\n<a id=\"routed-component-w-param\"></a>\n<h2 id=\"routed-components\">Routed components<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#routed-components\"><i class=\"material-icons\">link</i></a></h2>\n<p>A <em>routed component</em> is the destination of a <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> navigation.\nIt can be trickier to test, especially when the route to the component <em>includes parameters</em>.\nThe <code>HeroDetailComponent</code> is a <em>routed component</em> that is the destination of such a route.</p>\n<p>When a user clicks a <em>Dashboard</em> hero, the <code>DashboardComponent</code> tells the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code>\nto navigate to <code>heroes/:id</code>.\nThe <code>:id</code> is a route parameter whose value is the <code>id</code> of the hero to edit.</p>\n<p>The <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> matches that URL to a route to the <code>HeroDetailComponent</code>.\nIt creates an <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> object with the routing information and\ninjects it into a new instance of the <code>HeroDetailComponent</code>.</p>\n<p>Here's the <code>HeroDetailComponent</code> constructor:</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.ts\" region=\"ctor\" header=\"app/hero/hero-detail.component.ts (constructor)\">\nconstructor(\n private heroDetailService: HeroDetailService,\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>,\n private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {\n}\n\n</code-example>\n<p>The <code>HeroDetail</code> component needs the <code>id</code> parameter so it can fetch\nthe corresponding hero via the <code>HeroDetailService</code>.\nThe component has to get the <code>id</code> from the <code><a href=\"api/router/ActivatedRoute#paramMap\" class=\"code-anchor\">ActivatedRoute.paramMap</a></code> property\nwhich is an <code>Observable</code>.</p>\n<p>It can't just reference the <code>id</code> property of the <code><a href=\"api/router/ActivatedRoute#paramMap\" class=\"code-anchor\">ActivatedRoute.paramMap</a></code>.\nThe component has to <em>subscribe</em> to the <code><a href=\"api/router/ActivatedRoute#paramMap\" class=\"code-anchor\">ActivatedRoute.paramMap</a></code> observable and be prepared\nfor the <code>id</code> to change during its lifetime.</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.ts\" region=\"ng-on-init\" header=\"app/hero/hero-detail.component.ts (ngOnInit)\">\nngOnInit(): void {\n // get hero when `id` param changes\n this.route.paramMap.subscribe(pmap => this.getHero(pmap.get('id')));\n}\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p>The <a href=\"guide/router-tutorial-toh#activated-route-in-action\">ActivatedRoute in action</a> section of the <a href=\"guide/router-tutorial-toh\">Router tutorial: tour of heroes</a> guide covers <code><a href=\"api/router/ActivatedRoute#paramMap\" class=\"code-anchor\">ActivatedRoute.paramMap</a></code> in more detail.</p>\n</div>\n<p>Tests can explore how the <code>HeroDetailComponent</code> responds to different <code>id</code> parameter values\nby manipulating the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> injected into the component's constructor.</p>\n<p>You know how to spy on the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> and a data service.</p>\n<p>You'll take a different approach with <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> because</p>\n<ul>\n<li><code>paramMap</code> returns an <code>Observable</code> that can emit more than one value\nduring a test.</li>\n<li>You need the router helper function, <code><a href=\"api/router/convertToParamMap\" class=\"code-anchor\">convertToParamMap</a>()</code>, to create a <code><a href=\"api/router/ParamMap\" class=\"code-anchor\">ParamMap</a></code>.</li>\n<li>Other <em>routed component</em> tests need a test double for <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code>.</li>\n</ul>\n<p>These differences argue for a re-usable stub class.</p>\n<h4 id=\"activatedroutestub\"><em>ActivatedRouteStub</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#activatedroutestub\"><i class=\"material-icons\">link</i></a></h4>\n<p>The following <code>ActivatedRouteStub</code> class serves as a test double for <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code>.</p>\n<code-example path=\"testing/src/testing/activated-route-stub.ts\" region=\"activated-route-stub\" header=\"testing/activated-route-stub.ts (ActivatedRouteStub)\">\nimport { <a href=\"api/router/convertToParamMap\" class=\"code-anchor\">convertToParamMap</a>, <a href=\"api/router/ParamMap\" class=\"code-anchor\">ParamMap</a>, <a href=\"api/router/Params\" class=\"code-anchor\">Params</a> } from '@angular/router';\nimport { ReplaySubject } from 'rxjs';\n\n/**\n * An ActivateRoute test double with a `paramMap` observable.\n * Use the `setParamMap()` method to add the next `paramMap` value.\n */\nexport class ActivatedRouteStub {\n // Use a ReplaySubject to share previous values with subscribers\n // and pump new values into the `paramMap` observable\n private subject = new ReplaySubject&#x3C;<a href=\"api/router/ParamMap\" class=\"code-anchor\">ParamMap</a>>();\n\n constructor(initialParams?: <a href=\"api/router/Params\" class=\"code-anchor\">Params</a>) {\n this.setParamMap(initialParams);\n }\n\n /** The mock paramMap observable */\n readonly paramMap = this.subject.asObservable();\n\n /** Set the paramMap observables's next value */\n setParamMap(params?: <a href=\"api/router/Params\" class=\"code-anchor\">Params</a>) {\n this.subject.next(<a href=\"api/router/convertToParamMap\" class=\"code-anchor\">convertToParamMap</a>(params));\n }\n}\n\n</code-example>\n<p>Consider placing such helpers in a <code>testing</code> folder sibling to the <code>app</code> folder.\nThis sample puts <code>ActivatedRouteStub</code> in <code>testing/activated-route-stub.ts</code>.</p>\n<div class=\"alert is-helpful\">\n<p>Consider writing a more capable version of this stub class with\nthe <a href=\"guide/testing-components-scenarios#marble-testing\"><em>marble testing library</em></a>.</p>\n</div>\n<a id=\"tests-w-test-double\"></a>\n<h4 id=\"testing-with-activatedroutestub\">Testing with <em>ActivatedRouteStub</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#testing-with-activatedroutestub\"><i class=\"material-icons\">link</i></a></h4>\n<p>Here's a test demonstrating the component's behavior when the observed <code>id</code> refers to an existing hero:</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"route-good-id\" header=\"app/hero/hero-detail.component.spec.ts (existing id)\">\ndescribe('when navigate to existing hero', () => {\n let expectedHero: Hero;\n\n beforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n expectedHero = firstHero;\n activatedRoute.setParamMap({id: expectedHero.id});\n createComponent();\n }));\n\n it('should display that hero\\'s name', () => {\n expect(page.nameDisplay.textContent).toBe(expectedHero.name);\n });\n});\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p>The <code>createComponent()</code> method and <code>page</code> object are discussed <a href=\"guide/testing-components-scenarios#page-object\">below</a>.\nRely on your intuition for now.</p>\n</div>\n<p>When the <code>id</code> cannot be found, the component should re-route to the <code>HeroListComponent</code>.</p>\n<p>The test suite setup provided the same router spy <a href=\"guide/testing-components-scenarios#routing-component\">described above</a> which spies on the router without actually navigating.</p>\n<p>This test expects the component to try to navigate to the <code>HeroListComponent</code>.</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"route-bad-id\" header=\"app/hero/hero-detail.component.spec.ts (bad id)\">\ndescribe('when navigate to non-existent hero id', () => {\n beforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n activatedRoute.setParamMap({id: 99999});\n createComponent();\n }));\n\n it('should try to navigate back to hero list', () => {\n expect(page.gotoListSpy.calls.any()).toBe(true, 'comp.gotoList called');\n expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');\n });\n});\n\n</code-example>\n<p>While this app doesn't have a route to the <code>HeroDetailComponent</code> that omits the <code>id</code> parameter, it might add such a route someday.\nThe component should do something reasonable when there is no <code>id</code>.</p>\n<p>In this implementation, the component should create and display a new hero.\nNew heroes have <code>id=0</code> and a blank <code>name</code>. This test confirms that the component behaves as expected:</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"route-no-id\" header=\"app/hero/hero-detail.component.spec.ts (no id)\">\ndescribe('when navigate with no hero id', () => {\n beforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(createComponent));\n\n it('should have hero.id === 0', () => {\n expect(component.hero.id).toBe(0);\n });\n\n it('should display empty hero name', () => {\n expect(page.nameDisplay.textContent).toBe('');\n });\n});\n\n</code-example>\n<h2 id=\"nested-component-tests\">Nested component tests<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#nested-component-tests\"><i class=\"material-icons\">link</i></a></h2>\n<p>Component templates often have nested components, whose templates\nmay contain more components.</p>\n<p>The component tree can be very deep and, most of the time, the nested components\nplay no role in testing the component at the top of the tree.</p>\n<p>The <code>AppComponent</code>, for example, displays a navigation bar with anchors and their <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> directives.</p>\n<code-example path=\"testing/src/app/app.component.html\" header=\"app/app.component.html\">\n&#x3C;app-banner>&#x3C;/app-banner>\n&#x3C;app-welcome>&#x3C;/app-welcome>\n&#x3C;nav>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/dashboard\">Dashboard&#x3C;/a>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/heroes\">Heroes&#x3C;/a>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/about\">About&#x3C;/a>\n&#x3C;/nav>\n&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>&#x3C;/<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n\n</code-example>\n<p>While the <code>AppComponent</code> <em>class</em> is empty,\nyou may want to write unit tests to confirm that the links are wired properly\nto the <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> directives, perhaps for the reasons <a href=\"guide/testing-components-scenarios#why-stubbed-routerlink-tests\">explained below</a>.</p>\n<p>To validate the links, you don't need the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> to navigate and you don't\nneed the <code>&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></code> to mark where the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> inserts <em>routed components</em>.</p>\n<p>The <code>BannerComponent</code> and <code>WelcomeComponent</code>\n(indicated by <code>&#x3C;app-banner></code> and <code>&#x3C;app-welcome></code>) are also irrelevant.</p>\n<p>Yet any test that creates the <code>AppComponent</code> in the DOM will also create instances of\nthese three components and, if you let that happen,\nyou'll have to configure the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> to create them.</p>\n<p>If you neglect to declare them, the Angular compiler won't recognize the\n<code>&#x3C;app-banner></code>, <code>&#x3C;app-welcome></code>, and <code>&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></code> tags in the <code>AppComponent</code> template\nand will throw an error.</p>\n<p>If you declare the real components, you'll also have to declare <em>their</em> nested components\nand provide for <em>all</em> services injected in <em>any</em> component in the tree.</p>\n<p>That's too much effort just to answer a few simple questions about links.</p>\n<p>This section describes two techniques for minimizing the setup.\nUse them, alone or in combination, to stay focused on testing the primary component.</p>\n<a id=\"stub-component\"></a>\n<h5 id=\"stubbing-unneeded-components\">Stubbing unneeded components<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#stubbing-unneeded-components\"><i class=\"material-icons\">link</i></a></h5>\n<p>In the first technique, you create and declare stub versions of the components\nand directive that play little or no role in the tests.</p>\n<code-example path=\"testing/src/app/app.component.spec.ts\" region=\"component-stubs\" header=\"app/app.component.spec.ts (stub declaration)\">\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({selector: 'app-banner', template: ''})\nclass BannerStubComponent {\n}\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({selector: '<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>', template: ''})\nclass RouterOutletStubComponent {\n}\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({selector: 'app-welcome', template: ''})\nclass WelcomeStubComponent {\n}\n\n</code-example>\n<p>The stub selectors match the selectors for the corresponding real components.\nBut their templates and classes are empty.</p>\n<p>Then declare them in the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> configuration next to the\ncomponents, directives, and pipes that need to be real.</p>\n<code-example path=\"testing/src/app/app.component.spec.ts\" region=\"testbed-stubs\" header=\"app/app.component.spec.ts (TestBed stubs)\">\n<a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n declarations: [\n AppComponent, RouterLinkDirectiveStub, BannerStubComponent, RouterOutletStubComponent,\n WelcomeStubComponent\n ]\n })\n\n</code-example>\n<p>The <code>AppComponent</code> is the test subject, so of course you declare the real version.</p>\n<p>The <code>RouterLinkDirectiveStub</code>, <a href=\"guide/testing-components-scenarios#routerlink\">described later</a>, is a test version\nof the real <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> that helps with the link tests.</p>\n<p>The rest are stubs.</p>\n<a id=\"no-errors-schema\"></a>\n<h4 id=\"no_errors_schema\"><em>NO_ERRORS_SCHEMA</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#no_errors_schema\"><i class=\"material-icons\">link</i></a></h4>\n<p>In the second approach, add <code><a href=\"api/core/NO_ERRORS_SCHEMA\" class=\"code-anchor\">NO_ERRORS_SCHEMA</a></code> to the <code>TestBed.schemas</code> metadata.</p>\n<code-example path=\"testing/src/app/app.component.spec.ts\" region=\"no-errors-schema\" header=\"app/app.component.spec.ts (NO_ERRORS_SCHEMA)\">\n<a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n declarations: [\n AppComponent,\n RouterLinkDirectiveStub\n ],\n schemas: [<a href=\"api/core/NO_ERRORS_SCHEMA\" class=\"code-anchor\">NO_ERRORS_SCHEMA</a>]\n })\n\n</code-example>\n<p>The <code><a href=\"api/core/NO_ERRORS_SCHEMA\" class=\"code-anchor\">NO_ERRORS_SCHEMA</a></code> tells the Angular compiler to ignore unrecognized elements and attributes.</p>\n<p>The compiler will recognize the <code>&#x3C;app-root></code> element and the <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a></code> attribute\nbecause you declared a corresponding <code>AppComponent</code> and <code>RouterLinkDirectiveStub</code>\nin the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> configuration.</p>\n<p>But the compiler won't throw an error when it encounters <code>&#x3C;app-banner></code>, <code>&#x3C;app-welcome></code>, or <code>&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></code>.\nIt simply renders them as empty tags and the browser ignores them.</p>\n<p>You no longer need the stub components.</p>\n<h4 id=\"use-both-techniques-together\">Use both techniques together<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#use-both-techniques-together\"><i class=\"material-icons\">link</i></a></h4>\n<p>These are techniques for <em>Shallow Component Testing</em> ,\nso-named because they reduce the visual surface of the component to just those elements\nin the component's template that matter for tests.</p>\n<p>The <code><a href=\"api/core/NO_ERRORS_SCHEMA\" class=\"code-anchor\">NO_ERRORS_SCHEMA</a></code> approach is the easier of the two but don't overuse it.</p>\n<p>The <code><a href=\"api/core/NO_ERRORS_SCHEMA\" class=\"code-anchor\">NO_ERRORS_SCHEMA</a></code> also prevents the compiler from telling you about the missing\ncomponents and attributes that you omitted inadvertently or misspelled.\nYou could waste hours chasing phantom bugs that the compiler would have caught in an instant.</p>\n<p>The <em>stub component</em> approach has another advantage.\nWhile the stubs in <em>this</em> example were empty,\nyou could give them stripped-down templates and classes if your tests\nneed to interact with them in some way.</p>\n<p>In practice you will combine the two techniques in the same setup,\nas seen in this example.</p>\n<code-example path=\"testing/src/app/app.component.spec.ts\" region=\"mixed-setup\" header=\"app/app.component.spec.ts (mixed setup)\">\n<a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n declarations: [\n AppComponent,\n BannerStubComponent,\n RouterLinkDirectiveStub\n ],\n schemas: [<a href=\"api/core/NO_ERRORS_SCHEMA\" class=\"code-anchor\">NO_ERRORS_SCHEMA</a>]\n })\n\n</code-example>\n<p>The Angular compiler creates the <code>BannerComponentStub</code> for the <code>&#x3C;app-banner></code> element\nand applies the <code>RouterLinkStubDirective</code> to the anchors with the <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a></code> attribute,\nbut it ignores the <code>&#x3C;app-welcome></code> and <code>&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></code> tags.</p>\n<a id=\"routerlink\"></a>\n<h2 id=\"components-with-routerlink\">Components with <em>RouterLink</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#components-with-routerlink\"><i class=\"material-icons\">link</i></a></h2>\n<p>The real <code>RouterLinkDirective</code> is quite complicated and entangled with other components\nand directives of the <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code>.\nIt requires challenging setup to mock and use in tests.</p>\n<p>The <code>RouterLinkDirectiveStub</code> in this sample code replaces the real directive\nwith an alternative version designed to validate the kind of anchor tag wiring\nseen in the <code>AppComponent</code> template.</p>\n<code-example path=\"testing/src/testing/router-link-directive-stub.ts\" region=\"router-link\" header=\"testing/router-link-directive-stub.ts (RouterLinkDirectiveStub)\">\n@<a href=\"api/core/Directive\" class=\"code-anchor\">Directive</a>({\n selector: '[<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]'\n})\nexport class RouterLinkDirectiveStub {\n @<a href=\"api/core/Input\" class=\"code-anchor\">Input</a>('<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>') linkParams: any;\n navigatedTo: any = null;\n\n @<a href=\"api/core/HostListener\" class=\"code-anchor\">HostListener</a>('click')\n onClick() {\n this.navigatedTo = this.linkParams;\n }\n}\n\n</code-example>\n<p>The URL bound to the <code>[<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]</code> attribute flows in to the directive's <code>linkParams</code> property.</p>\n<p>The <code><a href=\"api/core/HostListener\" class=\"code-anchor\">HostListener</a></code> wires the click event of the host element\n(the <code>&#x3C;a></code> anchor elements in <code>AppComponent</code>) to the stub directive's <code>onClick</code> method.</p>\n<p>Clicking the anchor should trigger the <code>onClick()</code> method,\nwhich sets the stub's telltale <code>navigatedTo</code> property.\nTests inspect <code>navigatedTo</code> to confirm that clicking the anchor\nsets the expected route definition.</p>\n<div class=\"alert is-helpful\">\n<p>Whether the router is configured properly to navigate with that route definition is a\nquestion for a separate set of tests.</p>\n</div>\n<a id=\"by-directive\"></a>\n<a id=\"inject-directive\"></a>\n<h4 id=\"bydirective-and-injected-directives\"><em>By.directive</em> and injected directives<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#bydirective-and-injected-directives\"><i class=\"material-icons\">link</i></a></h4>\n<p>A little more setup triggers the initial data binding and gets references to the navigation links:</p>\n<code-example path=\"testing/src/app/app.component.spec.ts\" region=\"test-setup\" header=\"app/app.component.spec.ts (test setup)\">\nbeforeEach(() => {\n fixture.detectChanges(); // <a href=\"api/animations/trigger\" class=\"code-anchor\">trigger</a> initial data binding\n\n // find DebugElements with an attached RouterLinkStubDirective\n linkDes = fixture.debugElement.queryAll(By.directive(RouterLinkDirectiveStub));\n\n // get attached link directive instances\n // using each <a href=\"api/core/DebugElement\" class=\"code-anchor\">DebugElement</a>'s injector\n routerLinks = linkDes.map(de => de.injector.get(RouterLinkDirectiveStub));\n});\n\n</code-example>\n<p>Three points of special interest:</p>\n<ol>\n<li>\n<p>You can locate the anchor elements with an attached directive using <code>By.directive</code>.</p>\n</li>\n<li>\n<p>The query returns <code><a href=\"api/core/DebugElement\" class=\"code-anchor\">DebugElement</a></code> wrappers around the matching elements.</p>\n</li>\n<li>\n<p>Each <code><a href=\"api/core/DebugElement\" class=\"code-anchor\">DebugElement</a></code> exposes a dependency injector with the\nspecific instance of the directive attached to that element.</p>\n</li>\n</ol>\n<p>The <code>AppComponent</code> links to validate are as follows:</p>\n<code-example path=\"testing/src/app/app.component.html\" region=\"links\" header=\"app/app.component.html (navigation links)\">\n&#x3C;nav>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/dashboard\">Dashboard&#x3C;/a>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/heroes\">Heroes&#x3C;/a>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/about\">About&#x3C;/a>\n&#x3C;/nav>\n\n</code-example>\n<a id=\"app-component-tests\"></a>\n<p>Here are some tests that confirm those links are wired to the <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a></code> directives\nas expected:</p>\n<code-example path=\"testing/src/app/app.component.spec.ts\" region=\"tests\" header=\"app/app.component.spec.ts (selected tests)\">\nit('can get RouterLinks from template', () => {\n expect(routerLinks.length).toBe(3, 'should have 3 routerLinks');\n expect(routerLinks[0].linkParams).toBe('/dashboard');\n expect(routerLinks[1].linkParams).toBe('/heroes');\n expect(routerLinks[2].linkParams).toBe('/about');\n});\n\nit('can click Heroes link in template', () => {\n const heroesLinkDe = linkDes[1]; // heroes link <a href=\"api/core/DebugElement\" class=\"code-anchor\">DebugElement</a>\n const heroesLink = routerLinks[1]; // heroes link directive\n\n expect(heroesLink.navigatedTo).toBeNull('should not have navigated yet');\n\n heroesLinkDe.triggerEventHandler('click', null);\n fixture.detectChanges();\n\n expect(heroesLink.navigatedTo).toBe('/heroes');\n});\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p>The \"click\" test <em>in this example</em> is misleading.\nIt tests the <code>RouterLinkDirectiveStub</code> rather than the <em>component</em>.\nThis is a common failing of directive stubs.</p>\n<p>It has a legitimate purpose in this guide.\nIt demonstrates how to find a <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> element, click it, and inspect a result,\nwithout engaging the full router machinery.\nThis is a skill you may need to test a more sophisticated component, one that changes the display,\nre-calculates parameters, or re-arranges navigation options when the user clicks the link.</p>\n</div>\n<a id=\"why-stubbed-routerlink-tests\"></a>\n<h4 id=\"what-good-are-these-tests\">What good are these tests?<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#what-good-are-these-tests\"><i class=\"material-icons\">link</i></a></h4>\n<p>Stubbed <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> tests can confirm that a component with links and an outlet is setup properly,\nthat the component has the links it should have, and that they are all pointing in the expected direction.\nThese tests do not concern whether the app will succeed in navigating to the target component when the user clicks a link.</p>\n<p>Stubbing the RouterLink and RouterOutlet is the best option for such limited testing goals.\nRelying on the real router would make them brittle.\nThey could fail for reasons unrelated to the component.\nFor example, a navigation guard could prevent an unauthorized user from visiting the <code>HeroListComponent</code>.\nThat's not the fault of the <code>AppComponent</code> and no change to that component could cure the failed test.</p>\n<p>A <em>different</em> battery of tests can explore whether the application navigates as expected\nin the presence of conditions that influence guards such as whether the user is authenticated and authorized.</p>\n<div class=\"alert is-helpful\">\n<p>A future guide update will explain how to write such\ntests with the <code><a href=\"api/router/testing/RouterTestingModule\" class=\"code-anchor\">RouterTestingModule</a></code>.</p>\n</div>\n<a id=\"page-object\"></a>\n<h2 id=\"use-a-page-object\">Use a <em>page</em> object<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#use-a-page-object\"><i class=\"material-icons\">link</i></a></h2>\n<p>The <code>HeroDetailComponent</code> is a simple view with a title, two hero fields, and two buttons.</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/testing/hero-detail.component.png\" alt=\"HeroDetailComponent in action\" width=\"269\" height=\"170\">\n</div>\n<p>But there's plenty of template complexity even in this simple form.</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.html\" header=\"app/hero/hero-detail.component.html\">\n&#x3C;div *<a href=\"api/common/NgIf\" class=\"code-anchor\">ngIf</a>=\"hero\">\n &#x3C;h2>&#x3C;span>{{hero.name | <a href=\"api/common/TitleCasePipe\" class=\"code-anchor\">titlecase</a>}}&#x3C;/span> Details&#x3C;/h2>\n &#x3C;div>\n &#x3C;label>id: &#x3C;/label>{{hero.id}}&#x3C;/div>\n &#x3C;div>\n &#x3C;label for=\"name\">name: &#x3C;/label>\n &#x3C;input id=\"name\" [(<a href=\"api/forms/NgModel\" class=\"code-anchor\">ngModel</a>)]=\"hero.name\" placeholder=\"name\" />\n &#x3C;/div>\n &#x3C;button (click)=\"save()\">Save&#x3C;/button>\n &#x3C;button (click)=\"cancel()\">Cancel&#x3C;/button>\n&#x3C;/div>\n\n\n</code-example>\n<p>Tests that exercise the component need ...</p>\n<ul>\n<li>to wait until a hero arrives before elements appear in the DOM.</li>\n<li>a reference to the title text.</li>\n<li>a reference to the name input box to inspect and set it.</li>\n<li>references to the two buttons so they can click them.</li>\n<li>spies for some of the component and router methods.</li>\n</ul>\n<p>Even a small form such as this one can produce a mess of tortured conditional setup and CSS element selection.</p>\n<p>Tame the complexity with a <code>Page</code> class that handles access to component properties\nand encapsulates the logic that sets them.</p>\n<p>Here is such a <code>Page</code> class for the <code>hero-detail.component.spec.ts</code></p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"page\" header=\"app/hero/hero-detail.component.spec.ts (Page)\">\nclass Page {\n // getter properties wait to <a href=\"api/animations/query\" class=\"code-anchor\">query</a> the DOM until called.\n get buttons() {\n return this.queryAll&#x3C;HTMLButtonElement>('button');\n }\n get saveBtn() {\n return this.buttons[0];\n }\n get cancelBtn() {\n return this.buttons[1];\n }\n get nameDisplay() {\n return this.query&#x3C;HTMLElement>('span');\n }\n get nameInput() {\n return this.query&#x3C;HTMLInputElement>('input');\n }\n\n gotoListSpy: jasmine.Spy;\n navigateSpy: jasmine.Spy;\n\n constructor(someFixture: <a href=\"api/core/testing/ComponentFixture\" class=\"code-anchor\">ComponentFixture</a>&#x3C;HeroDetailComponent>) {\n // get the navigate spy from the injected router spy object\n const routerSpy = someFixture.debugElement.injector.get(<a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) as any;\n this.navigateSpy = routerSpy.navigate;\n\n // spy on component's `gotoList()` method\n const someComponent = someFixture.componentInstance;\n this.gotoListSpy = spyOn(someComponent, 'gotoList').and.callThrough();\n }\n\n //// <a href=\"api/animations/query\" class=\"code-anchor\">query</a> helpers ////\n private <a href=\"api/animations/query\" class=\"code-anchor\">query</a>&#x3C;T>(selector: string): T {\n return fixture.nativeElement.querySelector(selector);\n }\n\n private queryAll&#x3C;T>(selector: string): T[] {\n return fixture.nativeElement.querySelectorAll(selector);\n }\n}\n\n</code-example>\n<p>Now the important hooks for component manipulation and inspection are neatly organized and accessible from an instance of <code>Page</code>.</p>\n<p>A <code>createComponent</code> method creates a <code>page</code> object and fills in the blanks once the <code>hero</code> arrives.</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"create-component\" header=\"app/hero/hero-detail.component.spec.ts (createComponent)\">\n/** Create the HeroDetailComponent, initialize it, set test variables */\nfunction createComponent() {\n fixture = TestBed.createComponent(HeroDetailComponent);\n component = fixture.componentInstance;\n page = new Page(fixture);\n\n // 1st change detection triggers ngOnInit which gets a hero\n fixture.detectChanges();\n return fixture.whenStable().then(() => {\n // 2nd change detection displays the async-fetched hero\n fixture.detectChanges();\n });\n}\n\n</code-example>\n<p>The <a href=\"guide/testing-components-scenarios#tests-w-test-double\"><em>HeroDetailComponent</em> tests</a> in an earlier section demonstrate how <code>createComponent</code> and <code>page</code>\nkeep the tests short and <em>on message</em>.\nThere are no distractions: no waiting for promises to resolve and no searching the DOM for element values to compare.</p>\n<p>Here are a few more <code>HeroDetailComponent</code> tests to reinforce the point.</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"selected-tests\" header=\"app/hero/hero-detail.component.spec.ts (selected tests)\">\nit('should display that hero\\'s name', () => {\n expect(page.nameDisplay.textContent).toBe(expectedHero.name);\n});\n\nit('should navigate when click cancel', () => {\n click(page.cancelBtn);\n expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');\n});\n\nit('should save when click save but not navigate immediately', () => {\n // Get service injected into component and spy on its`saveHero` method.\n // It delegates to fake `HeroService.updateHero` which delivers a safe test result.\n const hds = fixture.debugElement.injector.get(HeroDetailService);\n const saveSpy = spyOn(hds, 'saveHero').and.callThrough();\n\n click(page.saveBtn);\n expect(saveSpy.calls.any()).toBe(true, 'HeroDetailService.save called');\n expect(page.navigateSpy.calls.any()).toBe(false, 'router.navigate not called');\n});\n\nit('should navigate when click save and save resolves', <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n click(page.saveBtn);\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(); // wait for async save to complete\n expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');\n }));\n\nit('should convert hero name to <a href=\"api/platform-browser/Title\" class=\"code-anchor\">Title</a> Case', () => {\n // get the name's input and display elements from the DOM\n const hostElement = fixture.nativeElement;\n const nameInput: HTMLInputElement = hostElement.querySelector('input');\n const nameDisplay: HTMLElement = hostElement.querySelector('span');\n\n // simulate user entering a new name into the input box\n nameInput.value = 'quick BROWN fOx';\n\n // Dispatch a DOM event so that Angular learns of input value change.\n // In older browsers, such as IE, you might need a CustomEvent instead. See\n // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill\n nameInput.dispatchEvent(new <a href=\"api/router/Event\" class=\"code-anchor\">Event</a>('input'));\n\n // Tell Angular to update the display binding through the title pipe\n fixture.detectChanges();\n\n expect(nameDisplay.textContent).toBe('Quick Brown Fox');\n});\n\n</code-example>\n<a id=\"compile-components\"></a>\n<h2 id=\"calling-compilecomponents\">Calling <em>compileComponents()</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#calling-compilecomponents\"><i class=\"material-icons\">link</i></a></h2>\n<div class=\"alert is-helpful\">\n<p>You can ignore this section if you <em>only</em> run tests with the CLI <code>ng test</code> command\nbecause the CLI compiles the application before running the tests.</p>\n</div>\n<p>If you run tests in a <strong>non-CLI environment</strong>, the tests may fail with a message like this one:</p>\n<code-example language=\"sh\" class=\"code-shell\" hidecopy=\"\">\nError: This test module uses the component BannerComponent\nwhich is using a \"templateUrl\" or \"styleUrls\", but they were never compiled.\nPlease call \"TestBed.compileComponents\" before your test.\n</code-example>\n<p>The root of the problem is at least one of the components involved in the test\nspecifies an external template or CSS file as\nthe following version of the <code>BannerComponent</code> does.</p>\n<code-example path=\"testing/src/app/banner/banner-external.component.ts\" header=\"app/banner/banner-external.component.ts (external template &#x26; css)\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a> } from '@angular/core';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-banner',\n templateUrl: './banner-external.component.html',\n styleUrls: ['./banner-external.component.css']\n})\nexport class BannerComponent {\n title = 'Test Tour of Heroes';\n}\n\n\n</code-example>\n<p>The test fails when the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> tries to create the component.</p>\n<code-example path=\"testing/src/app/banner/banner.component.spec.ts\" region=\"configure-and-create\" header=\"app/banner/banner.component.spec.ts (setup that fails)\" avoid=\"\">\nbeforeEach(() => {\n TestBed.configureTestingModule({\n declarations: [ BannerComponent ],\n });\n fixture = TestBed.createComponent(BannerComponent);\n});\n\n</code-example>\n<p>Recall that the app hasn't been compiled.\nSo when you call <code>createComponent()</code>, the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> compiles implicitly.</p>\n<p>That's not a problem when the source code is in memory.\nBut the <code>BannerComponent</code> requires external files\nthat the compiler must read from the file system,\nan inherently <em>asynchronous</em> operation.</p>\n<p>If the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> were allowed to continue, the tests would run and fail mysteriously\nbefore the compiler could finished.</p>\n<p>The preemptive error message tells you to compile explicitly with <code>compileComponents()</code>.</p>\n<h4 id=\"compilecomponents-is-async\"><em>compileComponents()</em> is async<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#compilecomponents-is-async\"><i class=\"material-icons\">link</i></a></h4>\n<p>You must call <code>compileComponents()</code> within an asynchronous test function.</p>\n<div class=\"alert is-critical\">\n<p>If you neglect to make the test function async\n(e.g., forget to use <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> as described below),\nyou'll see this error message</p>\n<code-example language=\"sh\" class=\"code-shell\" hidecopy=\"\">\nError: ViewDestroyedError: Attempt to use a destroyed view\n</code-example>\n</div>\n<p>A typical approach is to divide the setup logic into two separate <code>beforeEach()</code> functions:</p>\n<ol>\n<li>An async <code>beforeEach()</code> that compiles the components</li>\n<li>A synchronous <code>beforeEach()</code> that performs the remaining setup.</li>\n</ol>\n<p>To follow this pattern, import the <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> helper with the other testing symbols.</p>\n<code-example path=\"testing/src/app/banner/banner-external.component.spec.ts\" region=\"import-async\">\nimport { <a href=\"api/core/testing/ComponentFixture\" class=\"code-anchor\">ComponentFixture</a>, <a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>, <a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a> } from '@angular/core/testing';\n\n</code-example>\n<h4 id=\"the-async-beforeeach\">The async <em>beforeEach</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#the-async-beforeeach\"><i class=\"material-icons\">link</i></a></h4>\n<p>Write the first async <code>beforeEach</code> like this.</p>\n<code-example path=\"testing/src/app/banner/banner-external.component.spec.ts\" region=\"async-before-each\" header=\"app/banner/banner-external.component.spec.ts (async beforeEach)\">\nbeforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n <a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n declarations: [BannerComponent],\n })\n .compileComponents(); // compile template and css\n}));\n\n</code-example>\n<p>The <code><a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>()</code> helper function takes a parameterless function with the body of the setup.</p>\n<p>The <code>TestBed.configureTestingModule()</code> method returns the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> class so you can chain\ncalls to other <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> static methods such as <code>compileComponents()</code>.</p>\n<p>In this example, the <code>BannerComponent</code> is the only component to compile.\nOther examples configure the testing module with multiple components\nand may import application modules that hold yet more components.\nAny of them could require external files.</p>\n<p>The <code>TestBed.compileComponents</code> method asynchronously compiles all components configured in the testing module.</p>\n<div class=\"alert is-important\">\n<p>Do not re-configure the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> after calling <code>compileComponents()</code>.</p>\n</div>\n<p>Calling <code>compileComponents()</code> closes the current <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> instance to further configuration.\nYou cannot call any more <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> configuration methods, not <code>configureTestingModule()</code>\nnor any of the <code>override...</code> methods. The <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> throws an error if you try.</p>\n<p>Make <code>compileComponents()</code> the last step\nbefore calling <code>TestBed.createComponent()</code>.</p>\n<h4 id=\"the-synchronous-beforeeach\">The synchronous <em>beforeEach</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#the-synchronous-beforeeach\"><i class=\"material-icons\">link</i></a></h4>\n<p>The second, synchronous <code>beforeEach()</code> contains the remaining setup steps,\nwhich include creating the component and querying for elements to inspect.</p>\n<code-example path=\"testing/src/app/banner/banner-external.component.spec.ts\" region=\"sync-before-each\" header=\"app/banner/banner-external.component.spec.ts (synchronous beforeEach)\">\nbeforeEach(() => {\n fixture = TestBed.createComponent(BannerComponent);\n component = fixture.componentInstance; // BannerComponent test instance\n h1 = fixture.nativeElement.querySelector('h1');\n});\n\n</code-example>\n<p>You can count on the test runner to wait for the first asynchronous <code>beforeEach</code> to finish before calling the second.</p>\n<h4 id=\"consolidated-setup\">Consolidated setup<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#consolidated-setup\"><i class=\"material-icons\">link</i></a></h4>\n<p>You can consolidate the two <code>beforeEach()</code> functions into a single, async <code>beforeEach()</code>.</p>\n<p>The <code>compileComponents()</code> method returns a promise so you can perform the\nsynchronous setup tasks <em>after</em> compilation by moving the synchronous code\ninto a <code>then(...)</code> callback.</p>\n<code-example path=\"testing/src/app/banner/banner-external.component.spec.ts\" region=\"one-before-each\" header=\"app/banner/banner-external.component.spec.ts (one beforeEach)\">\nbeforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n <a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n declarations: [BannerComponent],\n })\n .compileComponents()\n .then(() => {\n fixture = TestBed.createComponent(BannerComponent);\n component = fixture.componentInstance;\n h1 = fixture.nativeElement.querySelector('h1');\n });\n}));\n\n</code-example>\n<h4 id=\"compilecomponents-is-harmless\"><em>compileComponents()</em> is harmless<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#compilecomponents-is-harmless\"><i class=\"material-icons\">link</i></a></h4>\n<p>There's no harm in calling <code>compileComponents()</code> when it's not required.</p>\n<p>The component test file generated by the CLI calls <code>compileComponents()</code>\neven though it is never required when running <code>ng test</code>.</p>\n<p>The tests in this guide only call <code>compileComponents</code> when necessary.</p>\n<a id=\"import-module\"></a>\n<h2 id=\"setup-with-module-imports\">Setup with module imports<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#setup-with-module-imports\"><i class=\"material-icons\">link</i></a></h2>\n<p>Earlier component tests configured the testing module with a few <code>declarations</code> like this:</p>\n<code-example path=\"testing/src/app/dashboard/dashboard-hero.component.spec.ts\" region=\"config-testbed\" header=\"app/dashboard/dashboard-hero.component.spec.ts (configure TestBed)\">\n<a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({declarations: [DashboardHeroComponent]})\n\n</code-example>\n<p>The <code>DashboardComponent</code> is simple. It needs no help.\nBut more complex components often depend on other components, directives, pipes, and providers\nand these must be added to the testing module too.</p>\n<p>Fortunately, the <code>TestBed.configureTestingModule</code> parameter parallels\nthe metadata passed to the <code>@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a></code> decorator\nwhich means you can also specify <code>providers</code> and <code>imports</code>.</p>\n<p>The <code>HeroDetailComponent</code> requires a lot of help despite its small size and simple construction.\nIn addition to the support it receives from the default testing module <code><a href=\"api/common/CommonModule\" class=\"code-anchor\">CommonModule</a></code>, it needs:</p>\n<ul>\n<li><code><a href=\"api/forms/NgModel\" class=\"code-anchor\">NgModel</a></code> and friends in the <code><a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a></code> to enable two-way data binding.</li>\n<li>The <code><a href=\"api/common/TitleCasePipe\" class=\"code-anchor\">TitleCasePipe</a></code> from the <code>shared</code> folder.</li>\n<li>Router services (which these tests are stubbing).</li>\n<li>Hero data access services (also stubbed).</li>\n</ul>\n<p>One approach is to configure the testing module from the individual pieces as in this example:</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"setup-forms-module\" header=\"app/hero/hero-detail.component.spec.ts (FormsModule setup)\">\nbeforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n const routerSpy = createRouterSpy();\n\n <a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n imports: [<a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>],\n declarations: [HeroDetailComponent, <a href=\"api/common/TitleCasePipe\" class=\"code-anchor\">TitleCasePipe</a>],\n providers: [\n {provide: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>, useValue: activatedRoute},\n {provide: HeroService, useClass: TestHeroService},\n {provide: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>, useValue: routerSpy},\n ]\n })\n .compileComponents();\n}));\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p>Notice that the <code>beforeEach()</code> is asynchronous and calls <code>TestBed.compileComponents</code>\nbecause the <code>HeroDetailComponent</code> has an external template and css file.</p>\n<p>As explained in <a href=\"guide/testing-components-scenarios#compile-components\"><em>Calling compileComponents()</em></a> above,\nthese tests could be run in a non-CLI environment\nwhere Angular would have to compile them in the browser.</p>\n</div>\n<h4 id=\"import-a-shared-module\">Import a shared module<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#import-a-shared-module\"><i class=\"material-icons\">link</i></a></h4>\n<p>Because many app components need the <code><a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a></code> and the <code><a href=\"api/common/TitleCasePipe\" class=\"code-anchor\">TitleCasePipe</a></code>, the developer created\na <code>SharedModule</code> to combine these and other frequently requested parts.</p>\n<p>The test configuration can use the <code>SharedModule</code> too as seen in this alternative setup:</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"setup-shared-module\" header=\"app/hero/hero-detail.component.spec.ts (SharedModule setup)\">\nbeforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n const routerSpy = createRouterSpy();\n\n <a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n imports: [SharedModule],\n declarations: [HeroDetailComponent],\n providers: [\n {provide: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>, useValue: activatedRoute},\n {provide: HeroService, useClass: TestHeroService},\n {provide: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>, useValue: routerSpy},\n ]\n })\n .compileComponents();\n}));\n\n</code-example>\n<p>It's a bit tighter and smaller, with fewer import statements (not shown).</p>\n<a id=\"feature-module-import\"></a>\n<h4 id=\"import-a-feature-module\">Import a feature module<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#import-a-feature-module\"><i class=\"material-icons\">link</i></a></h4>\n<p>The <code>HeroDetailComponent</code> is part of the <code>HeroModule</code> <a href=\"guide/feature-modules\">Feature Module</a> that aggregates more of the interdependent pieces\nincluding the <code>SharedModule</code>.\nTry a test configuration that imports the <code>HeroModule</code> like this one:</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"setup-hero-module\" header=\"app/hero/hero-detail.component.spec.ts (HeroModule setup)\">\nbeforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n const routerSpy = createRouterSpy();\n\n <a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n imports: [HeroModule],\n providers: [\n {provide: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>, useValue: activatedRoute},\n {provide: HeroService, useClass: TestHeroService},\n {provide: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>, useValue: routerSpy},\n ]\n })\n .compileComponents();\n}));\n\n</code-example>\n<p>That's <em>really</em> crisp. Only the <em>test doubles</em> in the <code>providers</code> remain. Even the <code>HeroDetailComponent</code> declaration is gone.</p>\n<p>In fact, if you try to declare it, Angular will throw an error because\n<code>HeroDetailComponent</code> is declared in both the <code>HeroModule</code> and the <code>DynamicTestModule</code>\ncreated by the <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code>.</p>\n<div class=\"alert is-helpful\">\n<p>Importing the component's feature module can be the easiest way to configure tests\nwhen there are many mutual dependencies within the module and\nthe module is small, as feature modules tend to be.</p>\n</div>\n<a id=\"component-override\"></a>\n<h2 id=\"override-component-providers\">Override component providers<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#override-component-providers\"><i class=\"material-icons\">link</i></a></h2>\n<p>The <code>HeroDetailComponent</code> provides its own <code>HeroDetailService</code>.</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.ts\" region=\"prototype\" header=\"app/hero/hero-detail.component.ts (prototype)\">\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-hero-detail',\n templateUrl: './hero-detail.component.html',\n styleUrls: ['./hero-detail.component.css' ],\n providers: [ HeroDetailService ]\n})\nexport class HeroDetailComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n constructor(\n private heroDetailService: HeroDetailService,\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>,\n private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {\n }\n}\n\n</code-example>\n<p>It's not possible to stub the component's <code>HeroDetailService</code> in the <code>providers</code> of the <code>TestBed.configureTestingModule</code>.\nThose are providers for the <em>testing module</em>, not the component. They prepare the dependency injector at the <em>fixture level</em>.</p>\n<p>Angular creates the component with its <em>own</em> injector, which is a <em>child</em> of the fixture injector.\nIt registers the component's providers (the <code>HeroDetailService</code> in this case) with the child injector.</p>\n<p>A test cannot get to child injector services from the fixture injector.\nAnd <code>TestBed.configureTestingModule</code> can't configure them either.</p>\n<p>Angular has been creating new instances of the real <code>HeroDetailService</code> all along!</p>\n<div class=\"alert is-helpful\">\n<p>These tests could fail or timeout if the <code>HeroDetailService</code> made its own XHR calls to a remote server.\nThere might not be a remote server to call.</p>\n<p>Fortunately, the <code>HeroDetailService</code> delegates responsibility for remote data access to an injected <code>HeroService</code>.</p>\n<code-example path=\"testing/src/app/hero/hero-detail.service.ts\" region=\"prototype\" header=\"app/hero/hero-detail.service.ts (prototype)\">\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>()\nexport class HeroDetailService {\n constructor(private heroService: HeroService) { }\n/* . . . */\n}\n\n</code-example>\n<p>The <a href=\"guide/testing-components-scenarios#feature-module-import\">previous test configuration</a> replaces the real <code>HeroService</code> with a <code>TestHeroService</code>\nthat intercepts server requests and fakes their responses.</p>\n</div>\n<p>What if you aren't so lucky. What if faking the <code>HeroService</code> is hard?\nWhat if <code>HeroDetailService</code> makes its own server requests?</p>\n<p>The <code>TestBed.overrideComponent</code> method can replace the component's <code>providers</code> with easy-to-manage <em>test doubles</em>\nas seen in the following setup variation:</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"setup-override\" header=\"app/hero/hero-detail.component.spec.ts (Override setup)\">\nbeforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n const routerSpy = createRouterSpy();\n\n <a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a>\n .configureTestingModule({\n imports: [HeroModule],\n providers: [\n {provide: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>, useValue: activatedRoute},\n {provide: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>, useValue: routerSpy},\n ]\n })\n\n // Override component's own provider\n .overrideComponent(\n HeroDetailComponent,\n {set: {providers: [{provide: HeroDetailService, useClass: HeroDetailServiceSpy}]}})\n\n .compileComponents();\n}));\n\n</code-example>\n<p>Notice that <code>TestBed.configureTestingModule</code> no longer provides a (fake) <code>HeroService</code> because it's <a href=\"guide/testing-components-scenarios#spy-stub\">not needed</a>.</p>\n<a id=\"override-component-method\"></a>\n<h4 id=\"the-overridecomponent-method\">The <em>overrideComponent</em> method<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#the-overridecomponent-method\"><i class=\"material-icons\">link</i></a></h4>\n<p>Focus on the <code>overrideComponent</code> method.</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"override-component-method\" header=\"app/hero/hero-detail.component.spec.ts (overrideComponent)\">\n.overrideComponent(\n HeroDetailComponent,\n {set: {providers: [{provide: HeroDetailService, useClass: HeroDetailServiceSpy}]}})\n\n</code-example>\n<p>It takes two arguments: the component type to override (<code>HeroDetailComponent</code>) and an override metadata object.\nThe <a href=\"guide/testing-utility-apis#metadata-override-object\">override metadata object</a> is a generic defined as follows:</p>\n<code-example language=\"javascript\">\n type <a href=\"api/core/testing/MetadataOverride\" class=\"code-anchor\">MetadataOverride</a>&#x3C;T> = {\n add?: Partial&#x3C;T>;\n remove?: Partial&#x3C;T>;\n set?: Partial&#x3C;T>;\n };\n</code-example>\n<p>A metadata override object can either add-and-remove elements in metadata properties or completely reset those properties.\nThis example resets the component's <code>providers</code> metadata.</p>\n<p>The type parameter, <code>T</code>, is the kind of metadata you'd pass to the <code>@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a></code> decorator:</p>\n<code-example language=\"javascript\">\n selector?: string;\n template?: string;\n templateUrl?: string;\n providers?: any[];\n ...\n</code-example>\n<a id=\"spy-stub\"></a>\n<h4 id=\"provide-a-spy-stub-herodetailservicespy\">Provide a <em>spy stub</em> (<em>HeroDetailServiceSpy</em>)<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#provide-a-spy-stub-herodetailservicespy\"><i class=\"material-icons\">link</i></a></h4>\n<p>This example completely replaces the component's <code>providers</code> array with a new array containing a <code>HeroDetailServiceSpy</code>.</p>\n<p>The <code>HeroDetailServiceSpy</code> is a stubbed version of the real <code>HeroDetailService</code>\nthat fakes all necessary features of that service.\nIt neither injects nor delegates to the lower level <code>HeroService</code>\nso there's no need to provide a test double for that.</p>\n<p>The related <code>HeroDetailComponent</code> tests will assert that methods of the <code>HeroDetailService</code>\nwere called by spying on the service methods.\nAccordingly, the stub implements its methods as spies:</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"hds-spy\" header=\"app/hero/hero-detail.component.spec.ts (HeroDetailServiceSpy)\">\nclass HeroDetailServiceSpy {\n testHero: Hero = {id: 42, name: 'Test Hero'};\n\n /* emit cloned test hero */\n getHero = jasmine.createSpy('getHero').and.callFake(\n () => asyncData(Object.assign({}, this.testHero)));\n\n /* emit clone of test hero, with changes merged in */\n saveHero = jasmine.createSpy('saveHero')\n .and.callFake((hero: Hero) => asyncData(Object.assign(this.testHero, hero)));\n}\n\n\n</code-example>\n<a id=\"override-tests\"></a>\n<h4 id=\"the-override-tests\">The override tests<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#the-override-tests\"><i class=\"material-icons\">link</i></a></h4>\n<p>Now the tests can control the component's hero directly by manipulating the spy-stub's <code>testHero</code>\nand confirm that service methods were called.</p>\n<code-example path=\"testing/src/app/hero/hero-detail.component.spec.ts\" region=\"override-tests\" header=\"app/hero/hero-detail.component.spec.ts (override tests)\">\nlet hdsSpy: HeroDetailServiceSpy;\n\nbeforeEach(<a href=\"api/core/testing/waitForAsync\" class=\"code-anchor\">waitForAsync</a>(() => {\n createComponent();\n // get the component's injected HeroDetailServiceSpy\n hdsSpy = fixture.debugElement.injector.get(HeroDetailService) as any;\n}));\n\nit('should have called `getHero`', () => {\n expect(hdsSpy.getHero.calls.count()).toBe(1, 'getHero called once');\n});\n\nit('should display stub hero\\'s name', () => {\n expect(page.nameDisplay.textContent).toBe(hdsSpy.testHero.name);\n});\n\nit('should save stub hero change', <a href=\"api/core/testing/fakeAsync\" class=\"code-anchor\">fakeAsync</a>(() => {\n const origName = hdsSpy.testHero.name;\n const newName = 'New Name';\n\n page.nameInput.value = newName;\n\n // In older browsers, such as IE, you might need a CustomEvent instead. See\n // https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent/CustomEvent#Polyfill\n page.nameInput.dispatchEvent(new <a href=\"api/router/Event\" class=\"code-anchor\">Event</a>('input')); // tell Angular\n\n expect(component.hero.name).toBe(newName, 'component hero has new name');\n expect(hdsSpy.testHero.name).toBe(origName, 'service hero unchanged before save');\n\n click(page.saveBtn);\n expect(hdsSpy.saveHero.calls.count()).toBe(1, 'saveHero called once');\n\n <a href=\"api/core/testing/tick\" class=\"code-anchor\">tick</a>(); // wait for async save to complete\n expect(hdsSpy.testHero.name).toBe(newName, 'service hero has new name after save');\n expect(page.navigateSpy.calls.any()).toBe(true, 'router.navigate called');\n }));\n\n</code-example>\n<a id=\"more-overrides\"></a>\n<h4 id=\"more-overrides\">More overrides<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/testing-components-scenarios#more-overrides\"><i class=\"material-icons\">link</i></a></h4>\n<p>The <code>TestBed.overrideComponent</code> method can be called multiple times for the same or different components.\nThe <code><a href=\"api/core/testing/TestBed\" class=\"code-anchor\">TestBed</a></code> offers similar <code>overrideDirective</code>, <code>overrideModule</code>, and <code>overridePipe</code> methods\nfor digging into and replacing parts of these other classes.</p>\n<p>Explore the options and combinations on your own.</p>\n\n \n</div>\n\n<!-- links to this doc:\n - guide/testing\n - guide/testing-attribute-directives\n - guide/testing-components-basics\n - guide/testing-utility-apis\n - guide/upgrade-setup\n-->\n<!-- links from this doc:\n - api/animations/query\n - api/animations/trigger\n - api/common/AsyncPipe\n - api/common/CommonModule\n - api/common/NgForOf\n - api/common/NgIf\n - api/common/TitleCasePipe\n - api/common/UpperCasePipe\n - api/common/http/HttpClient\n - api/core/AfterViewInit\n - api/core/Component\n - api/core/Component#styleUrls\n - api/core/Component#styles\n - api/core/Component#template\n - api/core/Component#templateUrl\n - api/core/DebugElement\n - api/core/Directive\n - api/core/ElementRef\n - api/core/EventEmitter\n - api/core/HostListener\n - api/core/Injectable\n - api/core/Input\n - api/core/NO_ERRORS_SCHEMA\n - api/core/NgModule\n - api/core/OnInit\n - api/core/Output\n - api/core/ViewChild\n - api/core/testing/ComponentFixture\n - api/core/testing/ComponentFixtureAutoDetect\n - api/core/testing/MetadataOverride\n - api/core/testing/TestBed\n - api/core/testing/fakeAsync\n - api/core/testing/flush\n - api/core/testing/tick\n - api/core/testing/waitForAsync\n - api/forms/FormsModule\n - api/forms/NgModel\n - api/platform-browser/Title\n - api/router/ActivatedRoute\n - api/router/ActivatedRoute#paramMap\n - api/router/Event\n - api/router/ParamMap\n - api/router/Params\n - api/router/Router\n - api/router/Router#events\n - api/router/RouterLink\n - api/router/RouterModule\n - api/router/RouterOutlet\n - api/router/convertToParamMap\n - api/router/testing/RouterTestingModule\n - guide/feature-modules\n - guide/http\n - guide/lifecycle-hooks\n - guide/router-tutorial-toh\n - guide/router-tutorial-toh#activated-route-in-action\n - guide/testing-components-basics#component-class-testing\n - guide/testing-components-scenarios#activatedroutestub\n - guide/testing-components-scenarios#async-observable-helpers\n - guide/testing-components-scenarios#async-observables\n - guide/testing-components-scenarios#async-test-with-fakeasync\n - guide/testing-components-scenarios#async-test-with-waitforasync\n - guide/testing-components-scenarios#automatic-change-detection\n - guide/testing-components-scenarios#bydirective-and-injected-directives\n - guide/testing-components-scenarios#calling-compilecomponents\n - guide/testing-components-scenarios#change-an-input-value-with-dispatchevent\n - guide/testing-components-scenarios#click-helper\n - guide/testing-components-scenarios#click-the-element\n - guide/testing-components-scenarios#clicking\n - guide/testing-components-scenarios#cold-observable\n - guide/testing-components-scenarios#comparing-dates-inside-fakeasync\n - guide/testing-components-scenarios#compile-components\n - guide/testing-components-scenarios#compilecomponents-is-async\n - guide/testing-components-scenarios#compilecomponents-is-harmless\n - guide/testing-components-scenarios#component-binding\n - guide/testing-components-scenarios#component-inside-a-test-host\n - guide/testing-components-scenarios#component-marble-tests\n - guide/testing-components-scenarios#component-override\n - guide/testing-components-scenarios#component-testing-scenarios\n - guide/testing-components-scenarios#component-with-a-dependency\n - guide/testing-components-scenarios#component-with-async-service\n - guide/testing-components-scenarios#component-with-external-files\n - guide/testing-components-scenarios#component-with-inputs-and-outputs\n - guide/testing-components-scenarios#components-with-routerlink\n - guide/testing-components-scenarios#consolidated-setup\n - guide/testing-components-scenarios#createcomponent-does-not-bind-data\n - guide/testing-components-scenarios#dashboard-hero-component\n - guide/testing-components-scenarios#detectchanges\n - guide/testing-components-scenarios#feature-module-import\n - guide/testing-components-scenarios#final-setup-and-tests\n - guide/testing-components-scenarios#get-injected-services\n - guide/testing-components-scenarios#import-a-feature-module\n - guide/testing-components-scenarios#import-a-shared-module\n - guide/testing-components-scenarios#jasmine-done\n - guide/testing-components-scenarios#jasmineclock-with-fakeasync\n - guide/testing-components-scenarios#learn-about-marble-testing\n - guide/testing-components-scenarios#marble-error-testing\n - guide/testing-components-scenarios#marble-frame\n - guide/testing-components-scenarios#marble-testing\n - guide/testing-components-scenarios#more-async-tests\n - guide/testing-components-scenarios#more-overrides\n - guide/testing-components-scenarios#nested-component-tests\n - guide/testing-components-scenarios#no_errors_schema\n - guide/testing-components-scenarios#override-component-providers\n - guide/testing-components-scenarios#page-object\n - guide/testing-components-scenarios#provide-a-spy-stub-herodetailservicespy\n - guide/testing-components-scenarios#provide-service-test-doubles\n - guide/testing-components-scenarios#query-for-the-h1\n - guide/testing-components-scenarios#routed-components\n - guide/testing-components-scenarios#routerlink\n - guide/testing-components-scenarios#routing-component\n - guide/testing-components-scenarios#setup-with-module-imports\n - guide/testing-components-scenarios#spy-stub\n - guide/testing-components-scenarios#stubbing-unneeded-components\n - guide/testing-components-scenarios#support-more-macrotasks\n - guide/testing-components-scenarios#synchronous-tests\n - guide/testing-components-scenarios#test-dashboardherocomponent-stand-alone\n - guide/testing-components-scenarios#testbedinject\n - guide/testing-components-scenarios#testing-with-a-spy\n - guide/testing-components-scenarios#testing-with-activatedroutestub\n - guide/testing-components-scenarios#tests-w-test-double\n - guide/testing-components-scenarios#the-async-beforeeach\n - guide/testing-components-scenarios#the-override-tests\n - guide/testing-components-scenarios#the-overridecomponent-method\n - guide/testing-components-scenarios#the-synchronous-beforeeach\n - guide/testing-components-scenarios#the-tick-function\n - guide/testing-components-scenarios#tickoptions\n - guide/testing-components-scenarios#triggereventhandler\n - guide/testing-components-scenarios#use-a-page-object\n - guide/testing-components-scenarios#use-both-techniques-together\n - guide/testing-components-scenarios#using-the-rxjs-scheduler-inside-fakeasync\n - guide/testing-components-scenarios#waitForAsync\n - guide/testing-components-scenarios#what-good-are-these-tests\n - guide/testing-components-scenarios#whenstable\n - guide/testing-components-scenarios#why-stubbed-routerlink-tests\n - guide/testing-utility-apis#metadata-override-object\n - http://reactivex.io/documentation/operators/defer.html\n - https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/button\n - https://github.com/angular/angular/edit/master/aio/content/guide/testing-components-scenarios.md?message=docs%3A%20describe%20your%20change...\n - https://jasmine.github.io/2.0/introduction.html#section-Asynchronous_Support\n - https://plnkr.co/\n - https://rxjs.dev/guide/testing/marble-testing\n - https://rxmarbles.com/\n-->"
}