Angular 角度7-可观测的有约束条件的单元测试

Angular 角度7-可观测的有约束条件的单元测试,angular,typescript,unit-testing,testing,angular7,Angular,Typescript,Unit Testing,Testing,Angular7,嗨,我正试图为一个具有可观察性的组件编写角度代码,但我无法测试subscribe函数。我应该如何访问订阅功能?任何帮助都将不胜感激。多谢各位 这是我的可观察组件: ngOnInit(): void { if (this.authService.getUser() !== null || this.authService.getUser() !== undefined) { console.log('getUser'); this.userService.us

嗨,我正试图为一个具有可观察性的组件编写角度代码,但我无法测试subscribe函数。我应该如何访问订阅功能?任何帮助都将不胜感激。多谢各位

这是我的可观察组件:

  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;
};
describe('AppComponent', () => {
  beforeEach(() => {
    let subscription: Subscription = new Subscription();
    TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      declarations: [AppComponent],
      providers: [WindowService, RoleService, HttpClient, HttpHandler, BroadcastService, MsalService,
        {
          provide: MSAL_CONFIG,  // MsalService needs config, this provides it.
          useFactory: () => ({   // Note this is an arrow fn that returns the config object
            redirectUri: window.location.origin + '/',
            clientID: mockData.clientID,
          }),
        }],
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
    }).compileComponents();
  });

  describe(':', () => {
    function setup() {
      const fixture = TestBed.createComponent(AppComponent);
      const app = fixture.debugElement.componentInstance;
      const compiled = fixture.debugElement.nativeElement;
      return {fixture, app, compiled};
    }

    it('Init with QA environment', () => {
      const {app} = setup();
      spyOn(app.authService, 'getUser').and.returnValue(mockData.userDetails);
      spyOn(app.authService, 'acquireTokenSilent').and.returnValue('msal:acquireTokenSuccess');
      app.ngOnInit();
      app.subscription.add(
        app.broadcastService.subscribe('msal:acquireTokenSuccess', () => {
        // do something here
        });
    );
这是我正在尝试的规范文件:

  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;
};
describe('AppComponent', () => {
  beforeEach(() => {
    let subscription: Subscription = new Subscription();
    TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      declarations: [AppComponent],
      providers: [WindowService, RoleService, HttpClient, HttpHandler, BroadcastService, MsalService,
        {
          provide: MSAL_CONFIG,  // MsalService needs config, this provides it.
          useFactory: () => ({   // Note this is an arrow fn that returns the config object
            redirectUri: window.location.origin + '/',
            clientID: mockData.clientID,
          }),
        }],
      schemas: [CUSTOM_ELEMENTS_SCHEMA]
    }).compileComponents();
  });

  describe(':', () => {
    function setup() {
      const fixture = TestBed.createComponent(AppComponent);
      const app = fixture.debugElement.componentInstance;
      const compiled = fixture.debugElement.nativeElement;
      return {fixture, app, compiled};
    }

    it('Init with QA environment', () => {
      const {app} = setup();
      spyOn(app.authService, 'getUser').and.returnValue(mockData.userDetails);
      spyOn(app.authService, 'acquireTokenSilent').and.returnValue('msal:acquireTokenSuccess');
      app.ngOnInit();
      app.subscription.add(
        app.broadcastService.subscribe('msal:acquireTokenSuccess', () => {
        // do something here
        });
    );

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

我们应该在创建新服务时创建服务的模拟。 示例代码:

从'@angular/common/http'导入{HttpClient};
从“@angular/core”导入{Injectable};
从'rxjs'导入{可观察的};
导出接口服务{
getUser():可观察的;
}
@注射的({
providedIn:'根'
})
导出类UserService实现IUserService{
构造函数(私有httpClient:httpClient){}
getUser():可观察{
返回此.httpClient.get('http://localhost:5000/api');
}
}
@可注射()
导出类MockUserService实现IUserService{
getUser():可观察{
常量用户:用户=。。。;
归还(用户);
}
}
在实际组件中创建服务模拟之后,假设您对组件中发生的事情一无所知。您应该知道的是,您将在初始化时登录(这是我从示例代码中解释的)

从“@angular/common”导入{CommonModule};
从“@angular/common/http/testing”导入{HttpClientTestingModule}”;
从“@angular/core/testing”导入{TestBed};
从“@angular/platform browser”导入{By}”;
从“@angular/router/testing”导入{RouterTestingModule}”;
从“@azure/msal angular”导入{MsalModule}”;
从“/app.component”导入{AppComponent};
从“/core/role.service”导入{RoleService}”;
描述(“AppComponent”,()=>{
在每个之前(()=>{
TestBed.configureTestingModule({
进口:[
路由器测试模块,
HttpClientTestingModule,
公共模块,
MsalModule.forRoot({
客户ID:“…”
})
],
声明:[AppComponent],
供应商:[
{
提供:用户服务,
useClass:MockUserService
},
{
提供:角色服务,
useClass:MockRoleService
}
]
}).compileComponents();
});
它(“应该创建应用程序”,()=>{
它(“应该创建应用程序”,()=>{
const fixture=TestBed.createComponent(AppComponent);
常量app=fixture.componentInstance;
expect(app.toBeTruthy();
});
});
它(“使用QA环境初始化”,异步()=>{
const fixture=TestBed.createComponent(AppComponent);
//在此方法中不要使用fixture.componentInstance。您的测试应该是
//在编写组件代码时,测试不应失败
//重构(方法/属性名称已更改)。
常量app=fixture.componentInstance;
//执行ngOnInit和其他启动代码
fixture.detectChanges();
//等待ngOnInit(及其订阅)完成
等待fixture.whenStable();
//在成功登录后,检查特定UI是否在HTML中可用
/**
* 
*你好
* 
*/
const helloElement=fixture.debugElement.query(By.css(“.hello”);
expect(helloElement.toBeTruthy();
});
它(“角色应该是数据管理员”,async()=>{
const fixture=TestBed.createComponent(AppComponent);
//Angular 9在以前的版本中使用TestBed.get(UserService)进行了注入
constuserservice=TestBed.inject(userService);
//执行ngOnInit和其他启动代码
fixture.detectChanges();
//等待ngOnInit(及其订阅)完成
等待fixture.whenStable();
expect(userService.userDetails.role).toBe(“数据管理员”);
});
});

我理解你的意思,但我正在尝试具体测试用户的角色,因此我需要访问确定角色的订阅方法。如果你能提出一些建议的话。这会很有帮助。您是否询问是否要检查用户是否导航到了
重定向URI
?或者我想根据这行检查角色
this.userService.userDetails.role=res?“数据管理员:'马赛克消费者'我编辑了测试代码并添加了另外一个测试用例
expect(userService.userDetails.role).toBe('datasteward')感谢您的回复,我非常感谢您的回复,但我发现此错误无法读取未定义的属性“subscribe”