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

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

Angular Unit Test: testing component with constructor injection

问题

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

LoginComponent.ts

  1. import { Component, Inject, OnInit } from '@angular/core';
  2. import { OKTA_AUTH } from '@okta/okta-angular';
  3. import { OktaAuth } from '@okta/okta-auth-js';
  4. @Component({
  5. selector: 'app-login',
  6. templateUrl: './login.component.html',
  7. styleUrls: ['./login.component.css']
  8. })
  9. export class LoginComponent implements OnInit {
  10. isAuthenticated!: boolean;
  11. userName?: string;
  12. error?: Error;
  13. constructor(@Inject(OKTA_AUTH) public oktaAuth: OktaAuth) {
  14. }
  15. async ngOnInit() {
  16. this.isAuthenticated = await this.oktaAuth.isAuthenticated();
  17. if (this.isAuthenticated) {
  18. const userClaims = await this.oktaAuth.getUser();
  19. this.userName = userClaims.name;
  20. }
  21. }
  22. async login() {
  23. try {
  24. await this.oktaAuth.signInWithRedirect();
  25. } catch (err: any) {
  26. console.error(err);
  27. this.error = err;
  28. }
  29. }
  30. async logout() {
  31. await this.oktaAuth.signOut();
  32. }
  33. }

LoginComponent.spec.ts

  1. import { ComponentFixture, TestBed } from '@angular/core/testing';
  2. import { LoginComponent } from './login.component';
  3. import { OktaAuth } from '@okta/okta-auth-js';
  4. describe('LoginComponent', () => {
  5. let component: LoginComponent;
  6. let fixture: ComponentFixture<LoginComponent>;
  7. let authService: OktaAuth;
  8. beforeEach(async () => {
  9. await TestBed.configureTestingModule({
  10. declarations: [LoginComponent],
  11. providers: [OktaAuth]
  12. }).compileComponents();
  13. fixture = TestBed.createComponent(LoginComponent);
  14. component = fixture.componentInstance;
  15. authService = TestBed.inject(OktaAuth);
  16. fixture.detectChanges();
  17. });
  18. it('should create', () => {
  19. expect(component).toBeTruthy();
  20. });
  21. });

这是错误信息:

  1. Chrome Headless 114.0.5735.133 (Windows 10) LoginComponent should create FAILED
  2. Error: NG0204: Can't resolve all parameters for OktaAuth: (?).
  3. 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)
  4. at providerToFactory (node_modules/@angular/core/fesm2022/core.mjs:9263:52)
  5. at providerToRecord (node_modules/@angular/core/fesm2022/core.mjs:9247:25)
  6. at R3Injector.processProvider (node_modules/@angular/core/fesm2022/core.mjs:9144:24)
  7. at fn (node_modules/@angular/core/fesm2022/core.mjs:8975:59)
  8. at forEachSingleProvider (node_modules/@angular/core/fesm2022/core.mjs:9318:13)
  9. at forEachSingleProvider (node_modules/@angular/core/fesm2022/core.mjs:9315:13)
  10. at new R3Injector (node_modules/@angular/core/fesm2022/core.mjs:8975:9)
  11. 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

  1. import { Component, Inject, OnInit } from &#39;@angular/core&#39;;
  2. import { OKTA_AUTH } from &#39;@okta/okta-angular&#39;;
  3. import { OktaAuth } from &#39;@okta/okta-auth-js&#39;;
  4. @Component({
  5. selector: &#39;app-login&#39;,
  6. templateUrl: &#39;./login.component.html&#39;,
  7. styleUrls: [&#39;./login.component.css&#39;]
  8. })
  9. export class LoginComponent implements OnInit {
  10. isAuthenticated!: boolean;
  11. userName?: string;
  12. error?: Error;
  13. constructor(@Inject(OKTA_AUTH) public oktaAuth: OktaAuth) {
  14. }
  15. async ngOnInit() {
  16. this.isAuthenticated = await this.oktaAuth.isAuthenticated();
  17. if (this.isAuthenticated) {
  18. const userClaims = await this.oktaAuth.getUser();
  19. this.userName = userClaims.name;
  20. }
  21. }
  22. async login() {
  23. try {
  24. await this.oktaAuth.signInWithRedirect();
  25. } catch (err: any) {
  26. console.error(err);
  27. this.error = err;
  28. }
  29. }
  30. async logout() {
  31. await this.oktaAuth.signOut();
  32. }
  33. }

LoginComponent.spec.ts

  1. import { ComponentFixture, TestBed } from &#39;@angular/core/testing&#39;;
  2. import { LoginComponent } from &#39;./login.component&#39;;
  3. import { OktaAuth } from &#39;@okta/okta-auth-js&#39;;
  4. describe(&#39;LoginComponent&#39;, () =&gt; {
  5. let component: LoginComponent;
  6. let fixture: ComponentFixture&lt;LoginComponent&gt;;
  7. let authService: OktaAuth;
  8. beforeEach(async () =&gt; {
  9. await TestBed.configureTestingModule({
  10. declarations: [LoginComponent],
  11. providers: [OktaAuth]
  12. }).compileComponents();
  13. fixture = TestBed.createComponent(LoginComponent);
  14. component = fixture.componentInstance;
  15. authService = TestBed.inject(OktaAuth);
  16. fixture.detectChanges();
  17. });
  18. it(&#39;should create&#39;, () =&gt; {
  19. expect(component).toBeTruthy();
  20. });
  21. });

Here is the error

  1. Chrome Headless 114.0.5735.133 (Windows 10) LoginComponent should create FAILED
  2. Error: NG0204: Can&#39;t resolve all parameters for OktaAuth: (?).
  3. 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)
  4. at providerToFactory (node_modules/@angular/core/fesm2022/core.mjs:9263:52)
  5. at providerToRecord (node_modules/@angular/core/fesm2022/core.mjs:9247:25)
  6. at R3Injector.processProvider (node_modules/@angular/core/fesm2022/core.mjs:9144:24)
  7. at fn (node_modules/@angular/core/fesm2022/core.mjs:8975:59)
  8. at forEachSingleProvider (node_modules/@angular/core/fesm2022/core.mjs:9318:13)
  9. at forEachSingleProvider (node_modules/@angular/core/fesm2022/core.mjs:9315:13)
  10. at new R3Injector (node_modules/@angular/core/fesm2022/core.mjs:8975:9)
  11. 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

  1. ...
  2. import { OktaAuthStateService, OKTA_AUTH } from '@okta/okta-angular';
  3. describe('AppComponent', () => {
  4. const authStateSpy = jasmine.createSpyObj('OktaAuthStateService', [], {
  5. authState$: of({
  6. isAuthenticated: false
  7. })
  8. });
  9. const authSpy = jasmine.createSpyObj('OktaAuth', ['login']);
  10. beforeEach(async () => {
  11. await TestBed.configureTestingModule({
  12. imports: [
  13. RouterTestingModule
  14. ],
  15. declarations: [
  16. AppComponent
  17. ],
  18. providers: [
  19. { provide: OktaAuthStateService, useValue: authStateSpy },
  20. { provide: OKTA_AUTH, useValue: authSpy } // <-- 看看如何提供令牌,但提供自己的存根/模拟?
  21. ]
  22. }).compileComponents();
  23. });
英文:

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

  1. ...
  2. import { OktaAuthStateService, OKTA_AUTH } from &#39;@okta/okta-angular&#39;;
  3. describe(&#39;AppComponent&#39;, () =&gt; {
  4. const authStateSpy = jasmine.createSpyObj(&#39;OktaAuthStateService&#39;, [], {
  5. authState$: of({
  6. isAuthenticated: false
  7. })
  8. });
  9. const authSpy = jasmine.createSpyObj(&#39;OktaAuth&#39;, [&#39;login&#39;]);
  10. beforeEach(async () =&gt; {
  11. await TestBed.configureTestingModule({
  12. imports: [
  13. RouterTestingModule
  14. ],
  15. declarations: [
  16. AppComponent
  17. ],
  18. providers: [
  19. { provide: OktaAuthStateService, useValue: authStateSpy },
  20. { provide: OKTA_AUTH, useValue: authSpy } // &lt;-- see how you can provide the token, but provide your own stub/mock?
  21. ]
  22. }).compileComponents();
  23. });

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:

确定