【问题标题】:angular2 execute unit tests from an external classangular2 从外部类执行单元测试
【发布时间】:2017-03-23 11:03:36
【问题描述】:

我正在做我的 angular2 测试。

我目前正在使用 ngx-translate 进行应用程序翻译,在进行翻译测试时,我想知道是否可以从外部帮助程序类对组件执行测试。

现在,我正在使用来自ngx-translate 的 HttpLoader,我可以毫无问题地执行我的第一个测试:

randomComponent.spec.ts

  it('should translate in english', async(() => {
    // Get the service
    translateService = TestBed.get(TranslateService);
    expect(translateService).toBeTruthy();
    checkTranslations(fixture, 'en', translateService);
  }));

  it('should translate in french', async(() => {
    // Get the service
    translateService = TestBed.get(TranslateService);
    expect(translateService).toBeTruthy();
    checkTranslations(fixture, 'fr', translateService);
  }));

translateHelper.ts

import { async, ComponentFixture } from '@angular/core/testing';
import { By } from '@angular/platform-browser';

export function checkTranslations(fixture: ComponentFixture<any>, language: string, translateService: any) {
  // Get all the content to be translated
  let contentToBeTranslated = fixture.debugElement.queryAll(By.css('*[translation]'));
  let beforeTranslationContent: string[] = [];

  contentToBeTranslated.forEach(debugElement => {
    beforeTranslationContent.push(debugElement.nativeElement.textContent);
  });

  // Test all english translations
  translateService.use(language).subscribe(() => {
    fixture.detectChanges();
    // Find missing translations
    contentToBeTranslated.forEach(debugElement => {
      expect(beforeTranslationContent.find(content => content == debugElement.nativeElement.textContent) ? true : false).toBe(false, ': Missing translation !');
    });
  });
}

到目前为止一切顺利,但如果我稍后添加语言,我将不得不为每种语言添加更多单元测试,如果我想测试我的翻译,我必须为每种语言复制/粘贴所有这些测试每个组件。


我的想法是创建一个可以获取当前组件 fixture 和 translateService 的类,但我如何将它与 beforeEach() 和所有内容联系起来?目前甚至有可能吗?

任何见解都会非常有帮助。

【问题讨论】:

  • 但是测试 ngx-translate 的目的是什么?与任何可靠的库一样,它已经被测试覆盖。我建议测试定义翻译的地方。这将是一个真正的单元测试。
  • 测试我的代码中是否有任何缺失的翻译。这只是一个开始,因为我对角度测试有点陌生
  • 一个好的单元测试只涉及被测试的部分。其他部分(在这种情况下是翻译服务)最好被存根/模拟。应该如何完成这取决于如何使用 ngx-translate。这不是 Angular 特有的,而是一般的单元测试。
  • 我同意,但是如果有人从文件中删除翻译,你如何测试回归?如果我的翻译文件中缺少键,此代码允许我检查任何文件,这非常整洁
  • 模拟服务根据文件检查翻译后的字符串,如果丢失则抛出错误。在实际服务中执行此操作涉及更多活动部件,并使测试变得不那么具体和更脆弱。从技术上讲,这是一个集成测试,而不是单元。

标签: angular karma-jasmine angular2-testing


【解决方案1】:

完全有可能。我们在测试中这样做了,让帮助程序确保测试代码的干性和可读性是一种很好的做法。

beforeEach() 接受一个函数,因此您唯一需要做的就是创建一个函数。

export module TestHelpers {
  export function createComponent<T>(component: Type<T>,
                                     moduleDef: TestModuleMetadata = {},
                                     afterCreationFn: ((helper: Helpers<T>) => void) = noop) {
    return async(() => {
      const fixture = TestBed
        .configureTestingModule(moduleDef)
        .createComponent(component);
      afterCreationFn(new Helpers(fixture));
      fixture.detectChanges();
    });
  }

export class Helpers<T> {
    fixture: ComponentFixture<T>;

    constructor(fixture: ComponentFixture<T>) {
      this.fixture = fixture;
    }

    component() {
      return this.fixture.componentInstance;
    }
}

}

在你的测试中

beforeEach(TestHelpers.createComponent(
    TestComponent,
    {
      imports: [],
      declarations: [
        TestComponent
      ]
    },
    (h: Helpers<TestComponent>) => {
      helper = h;
      componentInstance = helper.component();
  }));

然后您可以使用任何帮助函数来实现 Helper 类,以帮助您进行测试,所有这些都在一个地方完成

【讨论】:

  • 酷!不过我有两个问题:你的= noop 是什么?以及如何从根注入器管理服务注入?我从 TestBed 获得我的服务,并且通过这个设置我应该从组件注入器获得它?
  • noop 只是一个空操作函数()=&gt;{}。是的,这将是一种更正确的方法fixture.debugElement.injector.get(YourService);
  • 在尝试之后,我有点卡住了……你能提供一个Helper 的例子吗?由于fixture 在 Helper 中,这是否意味着您的所有测试都在此 Helper 中?
  • 是的,但您可以使用 helper.fixture 来访问灯具。 Fixture 存在,因此您可以使用它编写辅助函数,而不是直接调用 Fixture
猜你喜欢
  • 2017-06-15
  • 1970-01-01
  • 2019-02-03
  • 2017-07-01
  • 2018-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-09
相关资源
最近更新 更多