首页 > 解决方案 > 测试依赖于 2 个服务的组件

问题描述

我有一个使用服务来检索信息的组件。但是该服务还从静态变量 conf 中获取配置服务的配置。运行 karma 测试时,const 变量是未定义的。

我知道我可以创建模拟服务,但是我应该创建 2 个服务来测试这个组件吗?如果是的话,我还有其他服务也使用配置服务,所以我必须为每个服务创建模拟服务?似乎需要做很多工作,但我还没有找到更好的解决方案:(我提供了 ConfigurationService 和我正在使用的服务,如果这有什么不同的话。

TypeError: Cannot read property 'apiUrl' of undefined

apiUrl 是 conf 的一个属性,它是 ConfigurationService 中的一个静态变量。

配置服务.ts

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

import * as YAML from 'js-yaml';
import {Config} from './models/Config';


@Injectable()
export class ConfigService {
  public static  conf: Config;

  constructor(private http: HttpClient) {}
   async load() {
       const res = await this.http.get<Config>('assets/config.yml', {responseType: 'text' as 'json'}).toPromise();
       ConfigService.conf = YAML.load(res).environment;
  }
}

信息服务.ts

export class InfoService {
  private InfoUrl = ConfigService.conf.apiUrl + '/info';

  constructor(private http: HttpClient) {}
  getInfo(){
    return http.get(InfoUrl);
  }
}

信息组件.ts

export class InfoComponent implements OnInit {
  private info;
  constructor(private infoService: InfoService) {}

  ngOnInit() {}

  loadInfo() {
    this.info = this.infoService.getInfo();
  }

InfoComponent.spec.ts

import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { InfoComponent } from './info.component';
import {HttpClientModule} from '@angular/common/http';
import {InfoService} from './info.service';
import {ConfigService} from '../shared/config.service';


describe('InfoComponent', () => {
  let component: InfoComponent;
  let fixture: ComponentFixture<InfoComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientModule],
      declarations: [InfoComponent],
      providers: [
          ConfigService
          InfoService,
      ],
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(InfoComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

标签: angulartypescriptkarma-jasmine

解决方案


基本上你的组件需要InfoService。单元测试的核心概念围绕着隔离目标代码并对其进行测试。因此,在您的情况下,您不需要创建对ConfigService. 应该有一个单独的单元测试来测试ConfigService

class InfoServiceStub {
  getInfo(){
    return of({
        /// your mock data
     });
  }
}


describe('InfoComponent', () => {
  let component: InfoComponent;
  let fixture: ComponentFixture<InfoComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientModule],
      declarations: [InfoComponent],
      providers: [
          {provide: InfoService, useClass: InfoServiceStub },
      ],
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(InfoComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

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

推荐阅读