测试可观察物体角度2业力

Dem*_*ona 5 unit-testing karma-jasmine karma-coverage angular2-services angular

我正在使用Karma处理Angular 2的单元测试用例,我遇到了一个函数,我在下面运行测试

expect(component.subscribeToEvents()).toBeTruthy();
Run Code Online (Sandbox Code Playgroud)

我查看我的覆盖代码,测试文件中的行似乎没有覆盖订阅内的任何内容.我曾尝试使用MockBackend模拟服务函数内的api调用,但我不确定如何对订阅对象进行模拟,有人可以帮助我吗?

以下是test.component.ts

subscribeToEvents() {
this.subscription = this.czData.$selectedColorZone
  .subscribe(items => {
    this.resourceLoading = true;
    if (!this.resourceData || (this.resourceData && this.resourceData.length === 0)) {
      this.settings.layout.flypanel.display = false;
      this.getAllResources(this.pagination.start, this.pagination.size);
    }
    else {
      this.pagination.start = 1;
      this.pagination.end = this.pagination.size;
      this.getAllResources(1, this.pagination.size);
      this.settings.layout.flypanel.display = true;
    }
  });
return true;
Run Code Online (Sandbox Code Playgroud)

}

覆盖代码的屏幕截图 在此输入图像描述

Pau*_*tha 6

您不能这样做,因为订阅是异步解析的。因此同步测试在异步任务解决之前完成。

如果您想要的只是覆盖率,则可以进行 test async。这将导致 Angular 测试区在完成测试之前等待异步任务解决

import { async } from '@angular/core/testing';

it('..', async(() => {
  component.subscribeToEvents();
}))
Run Code Online (Sandbox Code Playgroud)

你不能在这里期待任何事情,因为当任务解决时没有回调钩子。所以这真的是一个毫无意义的测试。它会给你覆盖范围,但你实际上并没有测试任何东西。例如,您可能想要测试在解析订阅时是否设置了变量。

根据提供的代码,我要做的只是模拟服务,并使其同步。你怎么能这样做?我们可以让模拟像

class CzDataSub {
  items: any = [];

  $selectedColorZone = {
    subscribe: (callback: Function) => {
      callback(this.items);
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

然后在测试中配置就可以了

let czData: CzDataStub;

beforeEach(() => {
  czData = new CzDataStub();
  TestBed.configureTestingModule({
    providers: [
      { provide: CzData, useValue: czData }
    ]
  })
})
Run Code Online (Sandbox Code Playgroud)

现在在你的测试中,你不需要 make it async,你可以通过items在模拟上设置属性来提供你想要的任何值,订阅者会得到它

it('..', () => {
  czData.items = something;
  component.subscribeToEvents();
  expect(component.settings.layout.flypanel.display).toBe(false);
})
Run Code Online (Sandbox Code Playgroud)

更新

当我写这篇文章时,我想我是半睡半醒的。上述说法之一是不正确的

你不能在这里期待任何事情,因为当任务解决时没有回调钩子。

这并不完全正确。这fixture.whenStable()就是为了。例如,如果这是您的服务

class CzData {
  _value = new Subject<>();

  $selectedColorZone = this._value.asObservable();

  setValue(value) {
    this._value.next(value);
  }
}
Run Code Online (Sandbox Code Playgroud)

那么这就是你如何使测试工作

let czData: CzData;
let fixture: ComponentFixture<YourComponent>;
let component: YourComponent;

beforeEach(() => {
  TestBed.configureTestingModule({
    providers: [ CzData ],
    declarations: [ YourComponent ]
  });
  fixture = TestBed.createComponent(YourComponent);
  component = fixture.componentInstance;
  czData = TestBed.get(czData);
})

it('..', async(() => {
  component.subscribeToEvents();
  czData.setValue(somevalue);
  fixture.whenStable().then(() => {
    expect(component.settings.layout.flypanel.display).toBe(false);
  })
}))
Run Code Online (Sandbox Code Playgroud)

我们fixture.whenStable()用来等待异步任务完成。

这并不是说使用模拟是错误的。很多时候,使用模拟将是可行的方法。我只是想更正我的陈述,并展示如何做到这一点。