Angular单元测试:使用构造函数注入测试组件

huangapple go评论106阅读模式
英文:

Angular Unit Test: testing component with constructor injection

问题

我正在尝试为下面的登录组件编写单元测试。该组件的构造函数中使用了@Inject。我们如何测试带有@Inject构造函数的Angular组件?有人可以帮忙吗?谢谢!

LoginComponent.ts

import { Component, Inject, OnInit } from '@angular/core';
import { OKTA_AUTH } from '@okta/okta-angular';
import { OktaAuth } from '@okta/okta-auth-js';

@Component({
    selector: 'app-login',
    templateUrl: './login.component.html',
    styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
    isAuthenticated!: boolean;
    userName?: string;
    error?: Error;

    constructor(@Inject(OKTA_AUTH) public oktaAuth: OktaAuth) {  
    }

    async ngOnInit() {
        this.isAuthenticated = await this.oktaAuth.isAuthenticated();
        if (this.isAuthenticated) {
            const userClaims = await this.oktaAuth.getUser();
            this.userName = userClaims.name;
        }
    }
  
    async login() {
        try {
            await this.oktaAuth.signInWithRedirect();
        } catch (err: any) {
            console.error(err);
            this.error = err;
        }
    }
  
    async logout() {
        await this.oktaAuth.signOut();
    }
}

LoginComponent.spec.ts

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { LoginComponent } from './login.component';
import { OktaAuth } from '@okta/okta-auth-js';

describe('LoginComponent', () => {
    let component: LoginComponent;
    let fixture: ComponentFixture<LoginComponent>;
    let authService: OktaAuth;

    beforeEach(async () => {
        await TestBed.configureTestingModule({
            declarations: [LoginComponent],
            providers: [OktaAuth]
        }).compileComponents();

        fixture = TestBed.createComponent(LoginComponent);
        component = fixture.componentInstance;
        authService = TestBed.inject(OktaAuth);
        fixture.detectChanges();
    });

    it('should create', () => {
        expect(component).toBeTruthy();
    });
});

这是错误信息:

Chrome Headless 114.0.5735.133 (Windows 10) LoginComponent should create FAILED
Error: NG0204: Can't resolve all parameters for OktaAuth: (?).
error properties: Object({ code: 204 }) at getUndecoratedInjectableFactory (node_modules/@angular/core/fesm2022/core.mjs:9227:15) at injectableDefOrInjectorDefFactory (node_modules/@angular/core/fesm2022/core.mjs:9217:16)
    at providerToFactory (node_modules/@angular/core/fesm2022/core.mjs:9263:52)      
    at providerToRecord (node_modules/@angular/core/fesm2022/core.mjs:9247:25)       
    at R3Injector.processProvider (node_modules/@angular/core/fesm2022/core.mjs:9144:24)
    at fn (node_modules/@angular/core/fesm2022/core.mjs:8975:59)
    at forEachSingleProvider (node_modules/@angular/core/fesm2022/core.mjs:9318:13)  
    at forEachSingleProvider (node_modules/@angular/core/fesm2022/core.mjs:9315:13)  
    at new R3Injector (node_modules/@angular/core/fesm2022/core.mjs:8975:9)
    at createInjectorWithoutInjectorInstances (node_modules/@angular/core/fesm2022/core.mjs:10591:12)

我一定漏掉了什么。请告诉我我漏掉了什么。提前谢谢。

尝试导入以下两个:

import { OKTA_AUTH } from '@okta/okta-angular';
import { OktaAuth } from '@okta/okta-auth-js';

英文:

I am trying to write unit test for the login component below. This component has a constructor with @Inject. How do we test an angular component with @Inject in constructor? Can someone help? Thanks!

LoginComponent.ts

import { Component, Inject, OnInit } from &#39;@angular/core&#39;;
import { OKTA_AUTH } from &#39;@okta/okta-angular&#39;;
import { OktaAuth } from &#39;@okta/okta-auth-js&#39;;

@Component({
    selector: &#39;app-login&#39;,
    templateUrl: &#39;./login.component.html&#39;,
    styleUrls: [&#39;./login.component.css&#39;]
})
export class LoginComponent implements OnInit {
    isAuthenticated!: boolean;
    userName?: string;
    error?: Error;

    constructor(@Inject(OKTA_AUTH) public oktaAuth: OktaAuth) {  
    }

    async ngOnInit() {
        this.isAuthenticated = await this.oktaAuth.isAuthenticated();
        if (this.isAuthenticated) {
            const userClaims = await this.oktaAuth.getUser();
            this.userName = userClaims.name;
        }
  }
  
    async login() {
        try {
            await this.oktaAuth.signInWithRedirect();
        } catch (err: any) {
        
        console.error(err);
        this.error = err;
    }
  }
  
    async logout() {
        await this.oktaAuth.signOut();
    }

}

LoginComponent.spec.ts

import { ComponentFixture, TestBed } from &#39;@angular/core/testing&#39;;
import { LoginComponent } from &#39;./login.component&#39;;
import { OktaAuth } from &#39;@okta/okta-auth-js&#39;;

describe(&#39;LoginComponent&#39;, () =&gt; {
    let component: LoginComponent;
    let fixture: ComponentFixture&lt;LoginComponent&gt;;
    let authService: OktaAuth;

    beforeEach(async () =&gt; {
        await TestBed.configureTestingModule({
        declarations: [LoginComponent],
        providers: [OktaAuth]
    }).compileComponents();

    fixture = TestBed.createComponent(LoginComponent);
    component = fixture.componentInstance;
    authService = TestBed.inject(OktaAuth);
    fixture.detectChanges();
    });

    it(&#39;should create&#39;, () =&gt; {
        expect(component).toBeTruthy();
    });
});

Here is the error

Chrome Headless 114.0.5735.133 (Windows 10) LoginComponent should create FAILED
Error: NG0204: Can&#39;t resolve all parameters for OktaAuth: (?).
error properties: Object({ code: 204 }) at getUndecoratedInjectableFactory (node_modules/@angular/core/fesm2022/core.mjs:9227:15) at injectableDefOrInjectorDefFactory (node_modules/@angular/core/fesm2022/core.mjs:9217:16)
    at providerToFactory (node_modules/@angular/core/fesm2022/core.mjs:9263:52)      
    at providerToRecord (node_modules/@angular/core/fesm2022/core.mjs:9247:25)       
    at R3Injector.processProvider (node_modules/@angular/core/fesm2022/core.mjs:9144:24)
    at fn (node_modules/@angular/core/fesm2022/core.mjs:8975:59)
    at forEachSingleProvider (node_modules/@angular/core/fesm2022/core.mjs:9318:13)  
    at forEachSingleProvider (node_modules/@angular/core/fesm2022/core.mjs:9315:13)  
    at new R3Injector (node_modules/@angular/core/fesm2022/core.mjs:8975:9)
    at createInjectorWithoutInjectorInstances (node_modules/@angular/core/fesm2022/core.mjs:10591:12)

I must miss something. Please let me know what I am missing. Thanks in advance.

tried to import both
import { OKTA_AUTH } from '@okta/okta-angular';
import { OktaAuth } from '@okta/okta-auth-js';

答案1

得分: 1

这是我找到答案的地方:https://github.com/okta-samples/okta-angular-quickstart/blob/main/src/app/app.component.spec.ts

...

import { OktaAuthStateService, OKTA_AUTH } from '@okta/okta-angular';

describe('AppComponent', () => {
  const authStateSpy = jasmine.createSpyObj('OktaAuthStateService', [], {
    authState$: of({
      isAuthenticated: false
    })
  });

  const authSpy = jasmine.createSpyObj('OktaAuth', ['login']);

  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        AppComponent
      ],
      providers: [
        { provide: OktaAuthStateService, useValue: authStateSpy },
        { provide: OKTA_AUTH, useValue: authSpy } // <-- 看看如何提供令牌,但提供自己的存根/模拟?
      ]
    }).compileComponents();
  });
英文:

This is where I ended up finding the answer: https://github.com/okta-samples/okta-angular-quickstart/blob/main/src/app/app.component.spec.ts

...

import { OktaAuthStateService, OKTA_AUTH } from &#39;@okta/okta-angular&#39;;

describe(&#39;AppComponent&#39;, () =&gt; {
  const authStateSpy = jasmine.createSpyObj(&#39;OktaAuthStateService&#39;, [], {
    authState$: of({
      isAuthenticated: false
    })
  });

  const authSpy = jasmine.createSpyObj(&#39;OktaAuth&#39;, [&#39;login&#39;]);

  beforeEach(async () =&gt; {
    await TestBed.configureTestingModule({
      imports: [
        RouterTestingModule
      ],
      declarations: [
        AppComponent
      ],
      providers: [
        { provide: OktaAuthStateService, useValue: authStateSpy },
        { provide: OKTA_AUTH, useValue: authSpy } // &lt;-- see how you can provide the token, but provide your own stub/mock?  
      ]
    }).compileComponents();
  });

huangapple
  • 本文由 发表于 2023年8月9日 04:19:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76862952.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定