用Angular6来测试依赖于根参数的组件
结论
创建一个返回ParamMap的usevalue存根。
环境
> ng -v
_ _ ____ _ ___
/ \ _ __ __ _ _ _| | __ _ _ __ / ___| | |_ _|
/ △ \ | '_ \ / _` | | | | |/ _` | '__| | | | | | |
/ ___ \| | | | (_| | |_| | | (_| | | | |___| |___ | |
/_/ \_\_| |_|\__, |\__,_|_|\__,_|_| \____|_____|___|
|___/
Angular CLI: 6.1.3
Node: 10.8.0
OS: win32 x64
Angular: 6.1.2
... animations, common, compiler, compiler-cli, core, forms
... http, language-service, platform-browser
... platform-browser-dynamic, router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.7.3
@angular-devkit/build-angular 0.7.3
@angular-devkit/build-optimizer 0.7.3
@angular-devkit/build-webpack 0.7.3
@angular-devkit/core 0.7.3
@angular-devkit/schematics 0.7.3
@angular/cli 6.1.3
@ngtools/webpack 6.1.3
@schematics/angular 0.7.3
@schematics/update 0.7.3
rxjs 6.2.2
typescript 2.7.2
webpack 4.9.2
测试目标组件
使用HeroDetailComponent的公式教程。
但是这次的说明不涉及Location和Input部分,已删除。
<div *ngIf="hero">
<h2>{{hero.name | uppercase}} Details</h2>
<div><span>id: </span>{{hero.id}}</div>
<div>
name:{{hero.name}}
</div>
</div>
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router';
import { Hero } from '../hero';
import { HeroService } from '../hero.service';
@Component({
selector: 'app-hero-detail',
templateUrl: './hero-detail.component.html',
styleUrls: ['./hero-detail.component.scss']
})
export class HeroDetailComponent implements OnInit {
hero: Hero;
constructor(
private route: ActivatedRoute,
private heroService: HeroService
) { }
ngOnInit(): void {
this.getHero();
}
getHero(): void {
const id = +this.route.snapshot.paramMap.get('id');
this.heroService.getHero(id)
.subscribe(hero => this.hero = hero);
}
}
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HeroDetailComponent } from './hero-detail.component';
describe('HeroDetailComponent', () => {
let component: HeroDetailComponent;
let fixture: ComponentFixture<HeroDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [HeroDetailComponent]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeroDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
前修正
由于hero-detail.component.spec.ts保持着自动生成时的原始状态,所以测试必然失败。
>ng test
~~~~~(中略)~~~~~
Chrome 68.0.3440 (Windows 10 0.0.0) HeroDetailComponent should create FAILED
Error: StaticInjectorError(DynamicTestModule)[HeroDetailComponent -> ActivatedRoute]:
StaticInjectorError(Platform: core)[HeroDetailComponent -> ActivatedRoute]:
NullInjectorError: No provider for ActivatedRoute!
at NullInjector.get (webpack:///./node_modules/@angular/core/fesm5/core.js?:1359:19)
at resolveToken (webpack:///./node_modules/@angular/core/fesm5/core.js?:1597:24)
at tryResolveToken (webpack:///./node_modules/@angular/core/fesm5/core.js?:1541:16)
at StaticInjector.get (webpack:///./node_modules/@angular/core/fesm5/core.js?:1438:20)
at resolveToken (webpack:///./node_modules/@angular/core/fesm5/core.js?:1597:24)
at tryResolveToken (webpack:///./node_modules/@angular/core/fesm5/core.js?:1541:16)
at StaticInjector.get (webpack:///./node_modules/@angular/core/fesm5/core.js?:1438:20)
at resolveNgModuleDep (webpack:///./node_modules/@angular/core/fesm5/core.js?:8673:29)
at NgModuleRef_.get (webpack:///./node_modules/@angular/core/fesm5/core.js?:9361:16)
at resolveDep (webpack:///./node_modules/@angular/core/fesm5/core.js?:9726:45)
Expected undefined to be truthy.
at UserContext.eval (webpack:///./src/app/hero-detail/hero-detail.component.spec.ts?:20:27)
at ZoneDelegate.invoke (webpack:///./node_modules/zone.js/dist/zone.js?:387:26)
at ProxyZoneSpec.onInvoke (webpack:///./node_modules/zone.js/dist/zone-testing.js?:287:39)
修改部分
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
+import { ActivatedRoute, convertToParamMap } from '@angular/router';
import { HeroDetailComponent } from './hero-detail.component';
describe('HeroDetailComponent', () => {
let component: HeroDetailComponent;
let fixture: ComponentFixture<HeroDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
- declarations: [HeroDetailComponent]
+ declarations: [HeroDetailComponent],
+ providers: [{
+ provide: ActivatedRoute,
+ useValue: {
+ snapshot: { paramMap: convertToParamMap({ id: 11 }) }
+ }
}]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeroDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
-
- 生成 ActivatedRoute 的桩
使用 useValue 属性设置 snapshot 的返回值
使用 convertToParamMap 方法创建 ParamMap 对象会很方便
修正之后
由于这是一个已有的项目中添加的组件,请谅解测试数量的不同。
>ng test
~~~~~(中略)~~~~~
Chrome 68.0.3440 (Windows 10 0.0.0): Executed 11 of 11 SUCCESS (0.403 secs / 0.374 secs)
TOTAL: 11 SUCCESS
TOTAL: 11 SUCCESS
请提供更多的上下文信息。
-
- Angular – Testing
- angular – How to unit test a component that depends on parameters from ActivatedRoute?