How to unit test a component that depends on parameters from ActivatedRoute?
我正在对用于编辑对象的组件进行单元测试。 该对象具有唯一的
构造函数如下:
1 2 3 4 5 6 7 | constructor(private _router:Router, private _curRoute:ActivatedRoute, private _session:Session) { } ngOnInit() { this._curRoute.params.subscribe(params => { this.userId = params['id']; this.userObj = this._session.allUsers.filter(user => user.id.toString() === this.userId.toString())[0]; |
我想在此组件上运行基本的单元测试。 但是,我不确定如何注入
顺便说一句:我已经为
最简单的方法是使用
RxJS <6
1 2 3 4 5 6 7 8 9 | import { Observable } from 'rxjs/Observable'; import 'rxjs/add/observable/of'; ... { provide: ActivatedRoute, useValue: { params: Observable.of({id: 123}) } } |
RxJS> = 6
1 2 3 4 5 6 7 8 | import { of } from 'rxjs'; ... { provide: ActivatedRoute, useValue: { params: of({id: 123}) } } |
我已经知道如何做到这一点!
由于
1 2 3 4 5 | class MockActivatedRoute extends ActivatedRoute { constructor() { super(null, null, null, null, null); this.params = Observable.of({id:"5"}); } |
然后,与其他任何模拟服务一样,只需对其进行初始化并覆盖该组件的提供程序即可。
祝好运!
这是我在最新的angular 2.0中对其进行测试的方法...
1 | import { ActivatedRoute, Data } from '@angular/router'; |
和在提供商部分
1 2 3 4 5 6 7 8 9 10 | { provide: ActivatedRoute, useValue: { data: { subscribe: (fn: (value: Data) => void) => fn({ yourData: 'yolo' }) } } } |
在angular 8+中,提供了RouterTestingModule,您可以使用该模块来访问组件的ActivatedRoute或Router。您也可以将路由传递到RouterTestingModule并为请求的路由方法创建间谍。
例如,在我的组件中,我有:
1 2 3 4 | ngOnInit() { if (this.route.snapshot.paramMap.get('id')) this.editMode() this.titleService.setTitle(`${this.pageTitle} | ${TAB_SUFFIX}`) } |
在我的测试中,我有:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | beforeEach(async(() => { TestBed.configureTestingModule({ declarations: [ ProductLinePageComponent ], schemas: [NO_ERRORS_SCHEMA], imports: [ RouterTestingModule.withRoutes([]) ], }) .compileComponents() })) beforeEach(() => { router = TestBed.get(Router) route = TestBed.get(ActivatedRoute) }) |
然后在" it"部分中:
1 2 3 4 5 6 7 8 9 10 11 | it('should update', () => { const spyRoute = spyOn(route.snapshot.paramMap, 'get') spyRoute.and.returnValue('21') fixture = TestBed.createComponent(ProductLinePageComponent) component = fixture.componentInstance fixture.detectChanges() expect(component).toBeTruthy() expect(component.pageTitle).toBe('Edit Product Line') expect(component.formTitle).toBe('Edit Product Line') // here you can test the functionality which is triggered by the snapshot }) |
以类似的方式,我认为您可以通过返回一个可观察的对象或使用rxjs大理石通过茉莉花的spyOnProperty方法直接测试paramMap。这可能会节省一些时间,也不需要维护额外的模拟类。
希望它有用并且有意义。
只需添加一个ActivatedRoute的模拟:
1 2 3 | providers: [ { provide: ActivatedRoute, useClass: MockActivatedRoute } ] |
...
1 2 3 4 5 6 7 8 | class MockActivatedRoute { // here you can add your mock objects, like snapshot or parent or whatever // example: parent = { snapshot: {data: {title: 'myTitle ' } }, routeConfig: { children: { filter: () => {} } } }; } |
对于某些使用Angular> 5的人,如果Observable.of();无法工作,那么他们可以通过从'rxjs'导入import {of}来仅使用of();
为路由路径创建测试套件时遇到以下相同问题:
1 2 3 4 5 6 7 | { path: 'edit/:property/:someId', component: YourComponent, resolve: { yourResolvedValue: YourResolver } } |
在组件中,我将传递的属性初始化为:
1 2 3 4 | ngOnInit(): void { this.property = this.activatedRoute.snapshot.params.property; ... } |
运行测试时,如果未在模拟的ActivatedRoute" useValue"中传递属性值,则在使用" fixture.detectChanges()"检测更改时,将无法定义。这是因为ActivatedRoute的模拟值不包含属性params.property。然后,模拟useValue需要具有这些参数,以便灯具在组件中初始化" this.property"。您可以将其添加为:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | let fixture: ComponentFixture<YourComponent>; let component: YourComponent; let activatedRoute: ActivatedRoute; beforeEach(done => { TestBed.configureTestingModule({ declarations: [YourComponent], imports: [ YourImportedModules ], providers: [ YourRequiredServices, { provide: ActivatedRoute, useValue: { snapshot: { params: { property: 'yourProperty', someId: someId }, data: { yourResolvedValue: { data: mockResolvedData() } } } } } ] }) .compileComponents() .then(() => { fixture = TestBed.createComponent(YourComponent); component = fixture.debugElement.componentInstance; activatedRoute = TestBed.get(ActivatedRoute); fixture.detectChanges(); done(); }); }); |
您可以开始测试,例如:
1 2 3 4 | it('should ensure property param is yourProperty', async () => { expect(activatedRoute.snapshot.params.property).toEqual('yourProperty'); .... }); |
现在,假设您要测试其他属性值,然后可以将模拟的ActivatedRoute更新为:
1 2 3 4 5 6 7 8 9 | it('should ensure property param is newProperty', async () => { activatedRoute.snapshot.params.property = 'newProperty'; fixture = TestBed.createComponent(YourComponent); component = fixture.debugElement.componentInstance; activatedRoute = TestBed.get(ActivatedRoute); fixture.detectChanges(); expect(activatedRoute.snapshot.params.property).toEqual('newProperty'); }); |
希望这可以帮助!
在测试类中将提供程序添加为:
1 2 3 4 5 6 | { provide: ActivatedRoute, useValue: { paramMap: of({ get: v => { return { id: 123 }; } }) } } |