如何在单元测试中模拟环境文件导入

时间:2018-03-04 02:35:41

标签: angular jasmine

在我们的角度应用程序中,我们使用环境文件来加载一些配置。

environment.ts

export const environment = {
  production: false,
  defaultLocale: 'en_US',
};

然后我们在其中一项服务中使用它:

import { environment } from '../../environments/environment';
import { TranslateService } from './translate.service';

@Injectable()
export class LocaleService {
  constructor(private translateService: TranslateService){}

  useDefaultLocaleAsLang(): void {
    const defaultLocale = environment.defaultLocale;
    this.translateService.setUsedLang(defaultLocale);
  }
}

所以我在服务方法中使用环境文件中的值。

在我们的测试文件中,我们当然可以在translateService上使用Spy:

translateService = jasmine.createSpyObj('translateService', ['setUsedLang']);

但我不知道如何在我的测试文件中模拟环境值(例如在beforeEach中)。或者甚至将其转换为Subject以进行测试,以便我可以更改它并测试不同的行为。

更一般地说,如何在测试中模拟这些导入值以确保不使用实际值?

3 个答案:

答案 0 :(得分:4)

您无法测试/模拟environment.ts。它不是Angular DI系统的一部分,它是对文件系统上文件的硬性依赖。 Angular的编译过程使您可以在进行构建时替换掉不同的environment.*.ts文件。

Angular的DI系统是一种典型的面向对象的方法,可以使应用程序的各个部分更易于测试和配置。

我的建议是充分利用DI系统并尽量使用类似的方法     

import { environment } from '../../environments/environment';

代替Angular为这些依赖所做的事情,它希望您从中抽象出来。进行一项服务,在environment.ts数据和您的应用程序段之间提供一个接缝。

它不需要任何逻辑,它可以直接直接通过environment的属性(因此它本身不需要测试)。

然后在运行时依赖environment.ts的服务/组件中可以使用该服务,并且在测试时可以对其进行模拟,从environment.ts以外的其他地方获取数据

答案 1 :(得分:1)

类似的事情对我有用:

it('should test', () => {
  environment.defaultLocale = <location-to-test>;

  const result = service.method();

  expect(result).toEqual(<expected-result>);
});

答案 2 :(得分:0)

我在这种情况下使用的一种技术是创建包装器服务,例如EnvironmentService.ts,在这种情况下,它将返回环境配置。

这使我可以像其他任何EnvironmentService调用一样模拟对getEnvironmentConfiguration的{​​{1}}方法的调用。

然后可以在单元测试中修改环境变量:)