TypeError:this.oktaAuth.getUser 不是函数。在 Angular 中使用 Okta 库时单元测试用例失败

问题描述 投票:0回答:2

我正在使用 okta 库在 Angular8 中进行身份验证。到目前为止,功能运行良好,但项目要求是在 Angular8 中编写单元测试用例。下面是我的服务组件和规范文件的代码。

我正在创建一项公共服务(AccessCheck 服务),在其中检查来自 okta 库的用户访问并将结果返回给组件。使用该结果我在我的应用程序中进行 api 调用。当我运行应用程序时,功能运行正常。

但是当我在 Angular 中运行单元测试的基本设置时,它在 okta 的服务调用中失败并给出错误 okta get user is not a function。我不知道如何用角度为第三方库编写测试用例。任何帮助将不胜感激

我的代码

Access-CheckService.ts

@Injectable({
    providedIn: 'root'
})

export class AccessCheckService {

constructor(private router: Router,

        private oktaAuth: OktaAuthService, private commonService: CommonService) { }
 
async checkUserAcess() {
        let userAccess = {
            adminFlag: false,
            isOnlyuserRole: false
        }
        await this.oktaAuth.getUser().then((user) => {
       localStorage.setItem("userAcces", JSON.stringify(userAccess))
        return userAccess
})

async checkAdGroupsandProjectIds() {
        let projectDetails = JSON.parse(localStorage.getItem('ProjectDetails'))
        let userRole = JSON.parse(localStorage.getItem('userAcces'))
        if (!userRole) {
            userRole = await this.checkUserAcess()
        }
       let obj = {
            projectIds: projectDetails ,
            isOnlyuserRole: userRole 
        }
        return obj
    }

JobDetials.component.ts

export class JobDetailsComponent implements OnInit {

constructor(private jobDetailsService: JobDetailsService, private formBuilder: FormBuilder, private route: ActivatedRoute, 
    private commonService: CommonService,private router: Router,
    private accessCheck:AccessCheckService) { }

async ngOnInit() {   

    let userRoles = await this.accessCheck.checkAdGroupsandProjectIds()
    this.route.paramMap.subscribe(params => {
      this.details_id = params.get("id")    
    });


  if(!userRoles.isOnlyuserRole){
    this.getJobDetails(this.details_id,userRoles.projectIds,userRoles.isAdminFlag);
  }
}
 

JobDetails.component.spec.ts

describe('JobDetailsComponent', () => {

  let component: JobDetailsComponent;
  let fixture: ComponentFixture<JobDetailsComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [JobDetailsComponent],
      imports: [RouterTestingModule, MaterialModule, BrowserAnimationsModule, FormsModule, ReactiveFormsModule, HttpClientTestingModule,MatSnackBarModule],

      schemas: [ NO_ERRORS_SCHEMA ],

      providers: [{ provide: OktaAuthService, useValue: environment },AccessCheckService]
    })
      .compileComponents();
  }));

  beforeEach(() => {

    fixture = TestBed.createComponent(JobDetailsComponent);
    component = fixture.componentInstance;
    fixture.detectChanges()
  });

  it('should have job details component', () => {
    expect(component).toBeTruthy();
  });

  it('should have a title', () => {
    const compiled = fixture.nativeElement;
    fixture.detectChanges();                               /// failing here
    expect(compiled.querySelector('.title-container .title').textContent).toContain('Job Details:');
});

 

环境.ts

export const environment = {

  oktaIssuer: 'https://identity.mycompany.net',
  // oktaRedirectUrl: 'https://mycompany.net/signin',
  oktaRedirectUrl: 'http://localhost:4200/signin',
  oktaClientId: '1234Id',
  production: false
};


对于规范文件中编写的每个测试用例,我都会收到如下错误

TypeError: this.oktaAuth.getUser is not a function
TypeError: this.oktaAuth.getUser is not a function
    at AccessCheckService.<anonymous> (http://localhost:9876/_karma_webpack_/webpack:/src/app/services/accesscheck.service.ts:24:29)
 

如果我将规范文件中的提供者数组更改为

schemas: [ NO_ERRORS_SCHEMA ],

      providers: [OktaAuthService,AccessCheckService]

然后错误变为

your okta url is missing. you can copy your domain from the okta developer console
angular unit-testing authentication testing karma-jasmine
2个回答
0
投票

我知道这个问题很老了,但我想我会为将来查找这个问题的人回答这个问题。解决此问题的方法是添加 OktaAuth 作为提供程序并使用 Jasmin 间谍来模拟 get 用户调用,如下所示:

  {
      provide: OKTA_AUTH,
      useFactory: () => {
          const mockService = jasmine.createSpyObj('OktaAuth', ['getUser']);
          mockService.getUser.and.callFake(() => Promise.resolve({ name: 'Test' }));
          return mockService;
      }
  }

只需将其添加到您的单元测试提供程序数组中,您就可以开始了。


0
投票

要在上面 Joe Alvini 的答案中添加一点,他的答案对我有用,但我们在 Angular 应用程序中使用 jest 而不是 jasmine,所以我必须稍微修改他的答案才能为我们工作,这里是:

{
  provide: OKTA_AUTH,
  useFactory: () => {
    const mockService = {
      getUser: jest
        .fn()
        .mockReturnValue(Promise.resolve({ name: 'Test' })),
    };
    return mockService;
  },
},

© www.soinside.com 2019 - 2024. All rights reserved.