Angular2 单元测试不使用模拟服务

Jon*_*tes 2 unit-testing karma-jasmine angular

我正在测试一个非常简单的组件,它显示/隐藏登录/退出按钮。

\n\n

为此,我嘲笑我的AuthService服务,因为它依赖于 AngularFire2。

\n\n

我遇到的问题是,似乎Mock AuthService没有提供我的模拟服务 () 来代替实际的AuthService.

\n\n

在测试中should show the Facebook login buttonservice.isAnonymous预计是未定义的。实际服务中确实如此。但在模拟服务中是true。这个测试应该会失败。

\n\n

另外,请注意我正在尝试调用该方法service.test(false);;在模拟服务中,此方法存在并且是public。但我收到错误:

\n\n
\n

类型“AuthService”上不存在属性“test”。

\n
\n\n

这表明我的模拟服务没有被提供。

\n\n

您可以在我的测试规范中看到我如何尝试两种方式来提供模拟服务(其中一种已被注释掉):

\n\n
import { DebugElement } from '@angular/core';\nimport {\n  async,\n  inject,\n  ComponentFixture,\n  TestBed\n} from '@angular/core/testing';\nimport { By } from '@angular/platform-browser';\n\nimport { FacebookLoginComponent } from './facebook-login.component';\nimport { AuthService } from '../shared/auth.service';\nimport { MockAuthService } from '../shared/testing/auth.service';\n\ndescribe('FacebookLoginComponent', () => {\n  let authService: AuthService;\n  let component: FacebookLoginComponent;\n  let fixture: ComponentFixture<FacebookLoginComponent>;\n  let debugElement: DebugElement;\n  let htmlElement: HTMLElement;\n\n  beforeEach(async(() => {\n    TestBed.configureTestingModule({\n      declarations: [ FacebookLoginComponent ],\n      // providers: [{ provide: AuthService, useValue: MockAuthService }]\n    })\n      .compileComponents();\n\n    TestBed.overrideComponent(FacebookLoginComponent, {\n      set: {\n        providers: [{ provide: AuthService, useClass: MockAuthService }]\n      }\n    })\n  }));\n\n  beforeEach(() => {\n    fixture = TestBed.createComponent(FacebookLoginComponent);\n    component = fixture.componentInstance;\n    fixture.detectChanges();\n  });\n\n  it('should be created', () => {\n    expect(component).toBeTruthy();\n  });\n\n  it('should show the Facebook login button', inject([ AuthService ], (service: AuthService) => {\n    expect(service.isAnonymous).toBeUndefined();\n\n    debugElement = fixture.debugElement.query(By.css('button'));\n    htmlElement = debugElement.nativeElement;\n\n    service.test(false);\n\n    expect(htmlElement.textContent).toBe('Facebook Login');\n  }));\n\n  it('should show the Logout button', () => {\n    debugElement = fixture.debugElement.query(By.css('button'));\n    htmlElement = debugElement.nativeElement;\n\n    expect(htmlElement.textContent).toBe('Logout');\n  });\n});\n
Run Code Online (Sandbox Code Playgroud)\n\n

为了完整性;这是我的模拟服务MockAuthService

\n\n
import { Injectable } from '@angular/core';\n\n@Injectable()\nexport class MockAuthService {\n  public authState: { isAnonymous: boolean, uid: string };\n\n  constructor() {\n    this.authState = { isAnonymous: true, uid: '0HjUd9owxPZ5kibvUCN6S2DgB4x1' };\n  }\n\n  // public get currentUser(): firebase.User {\n  //   return this.authState ? this.authState : undefined;\n  // }\n\n  // public get currentUserObservable(): Observable<firebase.User> {\n  //   return this.afAuth.authState;\n  // }\n\n  public get currentUid(): string {\n    return this.authState ? this.authState.uid : undefined;\n  }\n\n  public get isAnonymous(): boolean {\n    return this.authState ? this.authState.isAnonymous : false;\n  }\n\n  public get isAuthenticated(): boolean {\n    return !!this.authState;\n  }\n\n  // public logout(): void {\n  //   this.afAuth.auth.signOut();\n  // }\n\n  public test(isAnonymous: boolean) {\n    this.authState.isAnonymous = isAnonymous;\n  }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

我不知道如何提供模拟。

\n\n

更新:

\n\n

根据到目前为止的答案和评论,我已经更新了我的模拟测试规范。但是,我仍然遇到同样的问题。

\n\n

我收到错误“AuthService”类型上不存在属性“test”。

\n\n

这表明它仍然没有用模拟来代替实际authService服务。

\n\n

此外,当我添加:

\n\n
public test(test: boolean): boolean {\n  return test;\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

到实际服务测试失败;但不是因为上面的错误,而是因为它应该 \xe2\x80\x94 未满足测试的期望。

\n\n

这是我更新的规格:

\n\n
import { DebugElement } from '@angular/core';\nimport {\n  async,\n  inject,\n  ComponentFixture,\n  TestBed\n} from '@angular/core/testing';\nimport { By } from '@angular/platform-browser';\n\nimport { FacebookLoginComponent } from './facebook-login.component';\nimport { AuthService } from '../shared/auth.service';\nimport { MockAuthService } from '../shared/testing/auth.service';\n\ndescribe('FacebookLoginComponent', () => {\n  let authService: AuthService;\n  let component: FacebookLoginComponent;\n  let fixture: ComponentFixture<FacebookLoginComponent>;\n  let debugElement: DebugElement;\n  let htmlElement: HTMLElement;\n\n  beforeEach(async(() => {\n    TestBed.configureTestingModule({\n      declarations: [ FacebookLoginComponent ],\n      providers: [{ provide: AuthService, useClass: MockAuthService }]\n    }).compileComponents();\n  }));\n\n  beforeEach(() => {\n    fixture = TestBed.createComponent(FacebookLoginComponent);\n    component = fixture.componentInstance;\n    fixture.detectChanges();\n  });\n\n  it('should be created', () => {\n    expect(component).toBeTruthy();\n  });\n\n  it('should show the Facebook Login button', inject([ AuthService ], (service: AuthService) => {\n    debugElement = fixture.debugElement.query(By.css('button'));\n    htmlElement = debugElement.nativeElement;\n\n    expect(htmlElement.textContent).toBe('Facebook Login');\n  }));\n\n  it('should show the Logout button', inject([ AuthService ], (service: AuthService) => {\n    expect(service.isAnonymous).toBe(true);\n\n    debugElement = fixture.debugElement.query(By.css('button'));\n    htmlElement = debugElement.nativeElement;\n\n    service.test(false);\n\n    fixture.detectChanges();\n\n    expect(htmlElement.textContent).toBe('Logout');\n  }));\n});\n
Run Code Online (Sandbox Code Playgroud)\n

Mic*_*zko 5

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ FacebookLoginComponent ],
      // providers: [{ provide: AuthService, useValue: MockAuthService }]
    })
      .compileComponents();

    TestBed.overrideComponent(FacebookLoginComponent, {
      set: {
        providers: [{ provide: AuthService, useClass: MockAuthService }]
      }
    })
  }));
Run Code Online (Sandbox Code Playgroud)

有两个问题。您不需要覆盖组件的提供程序,因为您可以在配置TestBed.

我假设您已经开始覆盖该组件,因为初始配置不起作用。它不起作用,因为您已经使用useValueuseClass.

  // providers: [{ provide: AuthService, useValue: MockAuthService }]
Run Code Online (Sandbox Code Playgroud)

这应该做:

beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [ FacebookLoginComponent ],
      providers: [{ provide: AuthService, useClass: MockAuthService }]
    }).compileComponents();
  }));
Run Code Online (Sandbox Code Playgroud)

编辑:

使用inject函数时,应将其用作MockAuthService类型。TypeScript 应该停止抱怨。

inject([ AuthService ], (service: MockAuthService) => { /* ... */ });
Run Code Online (Sandbox Code Playgroud)