Angular 2/Jasmine,在每个 describe/it 块内更新激活的路由参数订阅

Angular 2/Jasmine, updating an activated route params subscription within each describe/it block

给定一个订阅激活路由查询参数的简单组件 ngOnInit:

export class FooComponent implements OnInit {
  private queryParams: any;

  constructor(
    private activatedRoute: ActivatedRoute
  ) { }

  ngOnInit() {
    this.activatedRoute.queryParams.subscribe(params => this.queryParams = params);
  }

  active(foo: number): boolean {
    return this.queryParams['foo'] &&
      foo === +this.queryParams['foo'];
  }
}

foo 查询参数存在且其值与提供的参数匹配时,活动函数应 return 为真。

在该组件的附带单元测试中,我想更改每个 it 块中查询参数的值,以测试查询参数不存在、匹配参数和不匹配参数。

describe('FooComponent', () => {
  let component: FooComponent;
  let fixture: ComponentFixture<FooComponent>;
  let activatedRoute: ActivatedRoute;

  class MockActivatedRoute {
    queryParams = Observable.of({});
  }

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [FooComponent],
      providers: [
        { provide: ActivatedRoute, useClass: MockActivatedRoute }
      ]
    })
      .compileComponents();
  }));

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

    activatedRoute = fixture.debugElement.injector.get(ActivatedRoute);
  });

  describe('active', () => {
    it('should return false if the foo query param is not present', () => {
      activatedRoute.queryParams = Observable.of({});
      let result = component.active(100);
      expect(result).toBe(false);
    });

    it('should return false if the foo query param does not match the supplied parameter', () => {
      activatedRoute.queryParams = Observable.of({ foo: '500' });
      let result = component.active(100);
      expect(result).toBe(false);
    });

    it('should return true if the foo query param does not match the supplied parameter', () => {
      activatedRoute.queryParams = Observable.of({ foo: '500' });
      let result = component.active(500);
      expect(result).toBe(true);
    });
  });
});

FooComponent class 的私有 queryParams 成员的值不会在每个 it 块内更新。 asyncfixture.whenStable()fakeAsync/tick

的各种方法我都试过了

如何更新每个单元测试的订阅值?

这是因为你分配了一个新的Observable,但是客户端已经订阅了第一个Observable。发生这种情况是因为在您第一次调用 fixture.detectChanges() 时调用了 ngOnInit。如果您在 fixture.detectChanges() 之后等待调用 将新的 Observable 分配给 queryParams,那么将使用该 Observable。

另一种选择(可能是首选)是不使用 Observable,而是使用 Subject。有了这个,您可以控制何时发出数据以及发出什么。

import { Subject } from 'rxjs/Subject'
import { fakeAsync, tick } from

class MockActivatedRoute {
  queryParams = new Subject<any>();
}

let route: MockActivatedRoute;

beforeEach(() => {
  /* configure */ 

  route = <MockActivatedRoute>TestBed.get(ActivatedRoute);
})

it('', fakeAsync(() => {
  route.queryParams.next(newparams);    // emit something
  tick();                               // wait for resolution
  fixture.detectChanges();              // detect changes (for ui)
  expect(...)
}))

我说这个选项可能是首选,因为它允许在同一测试中发出多个值。