lundi 24 octobre 2016

Testing that a component behaves properly when the service it calls throws an exception with Angular 2

In my Angular 2 application, I'm trying to unit test the following component:

export class LoginComponent implements OnInit {
  invalidCredentials = false;
  unreachableBackend = false;

  constructor(private authService: AuthService) {}

  ngOnInit() {
    this.invalidCredentials = false;
  }

  onSubmit(user: any) {
    this.authService.authenticateUser(<User>user).subscribe((result) => {
      if (!result) {
        this.invalidCredentials = true;
      }
    }, (error) => {
      if (error instanceof InvalidCredentialsError) {
        this.invalidCredentials = true;
      } else {
        this.unreachableBackend = true;
      }
    });
  }
}

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:

describe('Authentication triggering an error', () => {
  class FakeAuthService {
    authenticateUser(user: User) {
      throw new InvalidCredentialsError();
    }
  }

  let component: LoginComponent;
  let fixture: ComponentFixture<LoginComponent>;
  let authService: AuthService;
  let spy: Spy;

  beforeEach(() => {
    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', () => {
    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');
  });
});

But when I run this test, I get the following failure:

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/unbox/frontend/src/app/login/login.component.spec.ts:112:44 <- src/test.ts:49782:67 onSubmit@webpack:///Users/sarbogast/dev/unbox/frontend/src/app/login/login.component.ts:9:4896 <- src/test.ts:85408:5955 webpack:///Users/sarbogast/dev/unbox/frontend/src/app/login/login.component.spec.ts:139:25 <- src/test.ts:49806:31 invoke@webpack:///Users/sarbogast/dev/unbox/frontend/~/zone.js/dist/zone.js:203:0 <- src/test.ts:84251:33 onInvoke@webpack:///Users/sarbogast/dev/unbox/frontend/~/zone.js/dist/proxy.js:72:0 <- src/test.ts:59204:45 invoke@webpack:///Users/sarbogast/dev/unbox/frontend/~/zone.js/dist/zone.js:202:0 <- src/test.ts:84250:42 run@webpack:///Users/sarbogast/dev/unbox/frontend/~/zone.js/dist/zone.js:96:0 <- src/test.ts:84144:49 webpack:///Users/sarbogast/dev/unbox/frontend/~/zone.js/dist/jasmine-patch.js:91:27 <- src/test.ts:58940:53 execute@webpack:///Users/sarbogast/dev/unbox/frontend/~/zone.js/dist/jasmine-patch.js:119:0 <- src/test.ts:58968:46 execute@webpack:///Users/sarbogast/dev/unbox/frontend/~/zone.js/dist/jasmine-patch.js:119:0 <- src/test.ts:58968:46 invokeTask@webpack:///Users/sarbogast/dev/unbox/frontend/~/zone.js/dist/zone.js:236:0 <- src/test.ts:84284:42 runTask@webpack:///Users/sarbogast/dev/unbox/frontend/~/zone.js/dist/zone.js:136:0 <- src/test.ts:84184:57 drainMicroTaskQueue@webpack:///Users/sarbogast/dev/unbox/frontend/~/zone.js/dist/zone.js:368:0 <- 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)

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.

Aucun commentaire:

Enregistrer un commentaire