title: Testing that a component behaves properly when the service it calls throws an exception with Angular 2
body: <p>In my Angular 2 application, I'm trying to unit test the following component:</p>
  
  <pre><code>export class LoginComponent implements OnInit {
    invalidCredentials = false;
    unreachableBackend = false;
  
    constructor(private authService: AuthService) {}
  
    ngOnInit() {
      this.invalidCredentials = false;
    }
  
    onSubmit(user: any) {
      this.authService.authenticateUser(&lt;User&gt;user).subscribe((result) =&gt; {
        if (!result) {
          this.invalidCredentials = true;
        }
      }, (error) =&gt; {
        if (error instanceof InvalidCredentialsError) {
          this.invalidCredentials = true;
        } else {
          this.unreachableBackend = true;
        }
      });
    }
  }
  </code></pre>
  
  <p>I have already successfully tested the happy path. Now I would like to check that when authService.authenticateUser() throws an error, invalidCredentials and unreachableBackend are correctly set. Here is what I am trying:</p>
  
  <pre><code>describe('Authentication triggering an error', () =&gt; {
    class FakeAuthService {
      authenticateUser(user: User) {
        throw new InvalidCredentialsError();
      }
    }
  
    let component: LoginComponent;
    let fixture: ComponentFixture&lt;LoginComponent&gt;;
    let authService: AuthService;
    let spy: Spy;
  
    beforeEach(() =&gt; {
      TestBed.configureTestingModule({
        declarations: [LoginComponent],
        providers: [
          {provide: AuthService, useClass: FakeAuthService},
          {provide: TranslateService, useClass: FakeTranslateService}
        ],
        imports: [ FormsModule, TranslateModule, AlertModule ]
      });
  
      fixture = TestBed.createComponent(LoginComponent);
      component = fixture.componentInstance;
      authService = fixture.debugElement.injector.get(AuthService);
      spy = spyOn(authService, 'authenticateUser').and.callThrough();
    });
  
    it('should not log in successfully if authentication fails', () =&gt; {
      const user = {username: 'username', password: 'password'};
      component.onSubmit(user);
  
      expect(authService.authenticateUser).toHaveBeenCalledWith(user);
      expect(spy.calls.count()).toEqual(1, 'authenticateUser should have been called once');
      expect(component.invalidCredentials).toBe(true, 'credentials should be invalid because of the exception');
      expect(component.unreachableBackend).toBe(false, 'backend should be reachable at first');
    });
  });
  </code></pre>
  
  <p>But when I run this test, I get the following failure:</p>
  
  <blockquote>
    <p>PhantomJS 2.1.1 (Mac OS X 0.0.0) Component: Login Authentication triggering an error should not log in successfully if authentication fails FAILED
            [object Object] thrown in src/test.ts (line 49782)
            authenticateUser@webpack:///Users/sarbogast/dev/myproject/frontend/src/app/login/login.component.spec.ts:112:44 &lt;- src/test.ts:49782:67
            onSubmit@webpack:///Users/sarbogast/dev/myproject/frontend/src/app/login/login.component.ts:9:4896 &lt;- src/test.ts:85408:5955
            webpack:///Users/sarbogast/dev/myproject/frontend/src/app/login/login.component.spec.ts:139:25 &lt;- src/test.ts:49806:31
            invoke@webpack:///Users/sarbogast/dev/myproject/frontend/~/zone.js/dist/zone.js:203:0 &lt;- src/test.ts:84251:33
            onInvoke@webpack:///Users/sarbogast/dev/myproject/frontend/~/zone.js/dist/proxy.js:72:0 &lt;- src/test.ts:59204:45
            invoke@webpack:///Users/sarbogast/dev/myproject/frontend/~/zone.js/dist/zone.js:202:0 &lt;- src/test.ts:84250:42
            run@webpack:///Users/sarbogast/dev/myproject/frontend/~/zone.js/dist/zone.js:96:0 &lt;- src/test.ts:84144:49
            webpack:///Users/sarbogast/dev/myproject/frontend/~/zone.js/dist/jasmine-patch.js:91:27 &lt;- src/test.ts:58940:53
            execute@webpack:///Users/sarbogast/dev/myproject/frontend/~/zone.js/dist/jasmine-patch.js:119:0 &lt;- src/test.ts:58968:46
            execute@webpack:///Users/sarbogast/dev/myproject/frontend/~/zone.js/dist/jasmine-patch.js:119:0 &lt;- src/test.ts:58968:46
            invokeTask@webpack:///Users/sarbogast/dev/myproject/frontend/~/zone.js/dist/zone.js:236:0 &lt;- src/test.ts:84284:42
            runTask@webpack:///Users/sarbogast/dev/myproject/frontend/~/zone.js/dist/zone.js:136:0 &lt;- src/test.ts:84184:57
            drainMicroTaskQueue@webpack:///Users/sarbogast/dev/myproject/frontend/~/zone.js/dist/zone.js:368:0 &lt;- src/test.ts:84416:42
    PhantomJS 2.1.1 (Mac OS X 0.0.0): Executed 33 of 38 (1 FAILED) (skipped 5) (0.704 secs / 0.842 secs)</p>
  </blockquote>
  
  <p>So obviously there is something I didn't get. I should mention the fact that I'm completely new to JS unit testing and somewhat new to reactive programming.</p>