当它调用的服务在Angular 2

时间:2016-10-24 12:46:03

标签: unit-testing testing angular typescript jasmine

在我的Angular 2应用程序中,我正在尝试对以下组件进行单元测试:

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;
      }
    });
  }
}

我已经成功测试了这条快乐的道路。现在我想检查一下当authService.authenticateUser()抛出错误时,invalidCredentials和unreachableBackend被正确设置。这是我正在尝试的:

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');
  });
});

但是当我运行此测试时,我得到以下失败:

  

PhantomJS 2.1.1(Mac OS X 0.0.0)组件:如果身份验证失败,则触发错误的登录身份验证不应成功登录失败           在src / test.ts中抛出[object Object](第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           调用@ 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           调用@ 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):执行33 of 38(1失败)(跳过5)(0.704秒/0.842秒)

显然,有些东西我没有得到。我应该提一下这样一个事实,即我对JS单元测试完全不熟悉,而且对于反应式编程也是新手。

1 个答案:

答案 0 :(得分:2)

你不能这样做,因为错误只会被抛出并冒泡到测试中。您需要做的是允许用户使用回调进行订阅,然后您可以调用错误回调。例如

class FakeAuthService {
  authenticateUser(user: User) {
    // return this service so user can call subscribe
    return this;
  }

  subscribe(onNext, onError) {
    if (onError) {
      onError(new InvalidCredentialsError());
    }
  }
}

另一种选择是使用Observable.throw(new InvalidCredentialsError())

authenticateUser(user: User) {
  return Observable.throw(new InvalidCredentialsError());
}

这将导致调用任何订阅者的onError回调。我个人喜欢使用模拟返回自己。我可以使模拟更易于配置,以使测试更容易。请参阅下面的链接,了解我的意思。

另见: