Angular 7-订阅的可观察单元测试

时间:2019-11-12 14:07:03

标签: angular typescript unit-testing testing angular7

嗨,我正在尝试为具有可观察性的组件编写角度代码,但无法测试订阅功能。我应该如何使用订阅功能?任何帮助,将不胜感激。谢谢。

这是我可观察到的部分:

.h

这是我正在尝试的规格文件:

  ngOnInit(): void {

    if (this.authService.getUser() !== null || this.authService.getUser() !== undefined) {
      console.log('getUser');
      this.userService.userDetails = this.authService.getUser();
    }

    if (this.environmentName === 'QA' || this.environmentName === 'LOCAL' || this.environmentName === 'QA-STAGING') {
      console.log('environmentName');
      this.authService.acquireTokenSilent(['api://012fdc3a-c966-4312-9b5c-301f097c1803/server']);
    } else {
      this.authService.acquireTokenSilent(['api://58a80bb5-906b-4ec0-9b41-7a78a07125af/server']);
    }

    this.subscription.add(
      this.broadcastService.subscribe('msal:acquireTokenSuccess', (payload) => {
        // do something here
        console.log('acquire token success ' + JSON.stringify(payload));

        this.roleService.checkServerEventReviewers().subscribe(res => {
          this.userService.userDetails.role = res ? 'Data Steward' : 'Mosaic Consumer';
          if (this.isLoggedIn !== true) {
            const redirectUri = sessionStorage.getItem('redirectUri');
            if (redirectUri !== undefined || redirectUri !== null) {
              this.router.navigateByUrl(redirectUri);
            }
          }
          this.isLoggedIn = true;
};

2 个答案:

答案 0 :(得分:1)

每当我们创建新的角度服务时,我们都应该创建服务的模拟。 示例代码:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable, of } from 'rxjs';

export interface IUserService {
  getUser(): Observable<User>;
}

@Injectable({
  providedIn: 'root'
})
export class UserService implements IUserService {

  constructor(private httpClient: HttpClient) {}
  getUser(): Observable<User> {
    return this.httpClient.get<User>('http://localhost:5000/api');
  }

}

@Injectable()
export class MockUserService implements IUserService {
  getUser(): Observable<User> {
    const user: User =  ...;
    return of(user);
  }

}

在您的实际组件中创建了服务模拟之后,假定您对组件中发生的事情一无所知。您应该知道的是,您将在初始化时登录(这是我从示例代码中所解释的)。

import { CommonModule } from "@angular/common";
import { HttpClientTestingModule } from "@angular/common/http/testing";
import { TestBed } from "@angular/core/testing";
import { By } from "@angular/platform-browser";
import { RouterTestingModule } from "@angular/router/testing";
import { MsalModule } from "@azure/msal-angular";
import { AppComponent } from "./app.component";
import { RoleService } from "./core/role.service";

describe("AppComponent", () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        HttpClientTestingModule,
        CommonModule,
        MsalModule.forRoot({
          clientID: "..."
        })
      ],
      declarations: [AppComponent],
      providers: [
        {
          provide: UserService,
          useClass: MockUserService
        },
        {
          provide: RoleService,
          useClass: MockRoleService
        }
      ]
    }).compileComponents();
  });

  it("Should create the app", () => {
    it("should create the app", () => {
      const fixture = TestBed.createComponent(AppComponent);
      const app = fixture.componentInstance;
      expect(app).toBeTruthy();
    });
  });

  it("Init with QA environment", async () => {
    const fixture = TestBed.createComponent(AppComponent);

    // Don't use fixture.componentInstance in this method. You tests should be 
    // written in such a way that tests shouldn't fail when component code is 
    // refactored(method/property names are changed).
    const app = fixture.componentInstance;

    // Execute ngOnInit and other startup code
    fixture.detectChanges();
    // Wait for ngOnInit(and its subscriptions) to complete
    await fixture.whenStable();

    // check if particular UI is available in HTML after successful login
    /**
     * <div *ngIf="loggedIn">
     * <span class="hello">Hello</span>
     * </div>
     */
    const helloElement = fixture.debugElement.query(By.css(".hello"));
    expect(helloElement).toBeTruthy();
  });

 it("Role should be Data Steward", async () => {
    const fixture = TestBed.createComponent(AppComponent);

    // Angular 9 has inject, in previous version, use TestBed.get(UserService)
    const userService = TestBed.inject(UserService);

    // Execute ngOnInit and other startup code
    fixture.detectChanges();
    // Wait for ngOnInit(and its subscriptions) to complete
    await fixture.whenStable();

    expect(userService.userDetails.role).toBe('Data Steward');
  });
});

答案 1 :(得分:0)

这不是您问题的直接答案,而是更多的间接问题。将所有这些业务逻辑都包含在组件中可能不是一个好主意。我建议使用一个库来协助您进行所有状态管理(我们使用NgRX)。然后,可以将许多这种逻辑移到服务或其他更易于测试的纯方法中。