给定一个简单的组件,订阅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
查询参数存在且其值与提供的参数匹配时,活动函数应返回true。
在此组件的附带单元测试中,我想更改每个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类的私有queryParams成员的值不会在每个it
块中更新。我尝试了async
,fixture.whenStable()
和fakeAsync/tick
的各种方法。
如何更新每个单元测试的订阅价值?
答案 0 :(得分:3)
这是因为您正在分配一个新的Observable,但客户端已经订阅了第一个Observable。这是因为首次调用ngOnInit
时会调用fixture.detectChanges()
。如果您在之后等待调用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(...)
}))
我说这个选项可能是首选,因为它允许在同一个测试中发出多个值。