繁体   English   中英

Angular 使用 APP_INITIALIZER 加载配置文件后测试失败

[英]Angular tests failing after using APP_INITIALIZER to load config file

我是 Angular 的新手,所以请原谅这个简单的问题。 我写了一个应用程序,它使用 HttpClient 和 APP_INITIALIZER 加载配置 json,但现在我的所有测试都失败并显示消息:类型错误:无法读取未定义的属性(读取“主题”)。 你能给我指出正确的方向吗?

app.component.spec.ts:

import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [RouterTestingModule],
      declarations: [AppComponent],
    }).compileComponents();
  });

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

app-config.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { firstValueFrom } from 'rxjs';

@Injectable({
  providedIn: 'root',
})
export class AppConfigService {
  static config: IAppConfig;

  constructor(private http: HttpClient) {}

  loadConfig() {
    return new Promise<void>(async (resolve, reject) => {
      try {
        const get$ = this.http.get('assets/app.config.json');
        const configFile = await firstValueFrom(get$);
        AppConfigService.config = <IAppConfig>configFile;
        resolve();
      } catch (e) {
        console.error('Error loading config file', e);
        reject(e);
      }
    });
  }
}

export interface IAppConfig {
  theme: string;
}

应用程序模块.ts

import { HttpClientModule } from '@angular/common/http';
import { NgModule, APP_INITIALIZER } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppConfigService } from './app-config.service';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

// Function to load application config on application startup
export function initializeApp(appConfigService: AppConfigService) {
  return (): Promise<any> => {
    return appConfigService.loadConfig();
  };
}

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule, HttpClientModule],
  providers: [
    AppConfigService,
    {
      provide: APP_INITIALIZER,
      useFactory: initializeApp,
      deps: [AppConfigService],
      multi: true,
    },
  ],
  bootstrap: [AppComponent],
})
export class AppModule {}

应用程序组件.ts

import { Component } from '@angular/core';
import { AppConfigService } from './app-config.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  theme = AppConfigService.config.theme;
}

你有几个问题,首先你不应该使用class来设置属性。 该服务应声明一些属性,并且在此服务中,您可以设置this.config = someValue

然后,如果你想在一个组件中使用服务,你必须注入它,基本上是通过依赖注入的构造函数: https://angular.io/guide/dependency-injection

constructor(heroService: HeroService)

然后您将添加服务 - 最好使用 mocking - 作为测试文件中的提供者。 您可以像这样使用来自 Jasmine 的Spy实现这一点:

https://codecraft.tv/courses/angular/unit-testing/mocks-and-spies/

另外,我会放弃更强大的 Observables Promises。 干杯!

所以我做了一些改变,这就是我带来的。 它正在工作,所有测试也都正常。 也不需要 APP_INITIALIZE。 你现在看到任何问题了吗?

app.component.spec.ts:

import { HttpClientTestingModule } from '@angular/common/http/testing';
import { TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';

describe('AppComponent', () => {
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [RouterTestingModule, HttpClientTestingModule],
      declarations: [AppComponent],
    }).compileComponents();
  });

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

app-config.service.ts:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable({
  providedIn: 'root',
})
export class AppConfigService {
  
  constructor(private http: HttpClient) {}

  loadConfig() {
    return this.http.get<IAppConfig>('assets/app.config.json');
  }
}

export interface IAppConfig {
  theme: string;
}

应用程序模块.ts:

import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

@NgModule({
  declarations: [AppComponent],
  imports: [BrowserModule, AppRoutingModule, HttpClientModule],
  bootstrap: [AppComponent],
})
export class AppModule {}

应用程序组件.ts:

import { Component } from '@angular/core';
import { AppConfigService, IAppConfig } from './app-config.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
})
export class AppComponent {
  config: IAppConfig = {
    theme: 'blue'
  };

  constructor(appConfigService: AppConfigService) {
    appConfigService.loadConfig().subscribe(data => this.config = data)
  }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM