Angular 如何模拟ActivatedRoute
我正在学习角度,我想做测试,但我被卡住了。我有一个函数:Angular 如何模拟ActivatedRoute,angular,unit-testing,angular-router,Angular,Unit Testing,Angular Router,我正在学习角度,我想做测试,但我被卡住了。我有一个函数: ngOnInit(): void { this.route.paramMap .switchMap((params: ParamMap) => this.SomethingService.getSomething(params.get('id'))) .subscribe(something => { this.something = something
ngOnInit(): void {
this.route.paramMap
.switchMap((params: ParamMap) =>
this.SomethingService.getSomething(params.get('id')))
.subscribe(something => {
this.something = something;
this.doSomethingElse();
});
}
在哪里
route: ActivatedRoute
我想测试它,但我不知道如何模拟ActivatedRoute模拟
ActivatedRoute
的一个简单方法是:
TestBed.configureTestingModule({
declarations: [YourComponenToTest],
providers: [
{
provide: ActivatedRoute,
useValue: {
params: Observable.from([{id: 1}]),
},
},
]
});
然后在您的测试中,它将是可用的,并且您的函数应该使用它(至少是ActivatedRoute部分)
如果要将它存储在变量中,可以使用TestBed.get(ActivatedRoute)
在it
函数中获取它
别忘了从
rxjs/Rx
导入可观测数据,而不是从rxjs/Observable
导入可观测数据。我在使用paramMap
而不是params
时遇到了同样的问题。这让它对我起了作用,至少在最简单的情况下:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Observable } from 'rxjs';
import 'rxjs/add/observable/of';
import { ComponentToTest } from './component-to-test.component';
import { ActivatedRoute } from '@angular/router';
TestBed.configureTestingModule({
declarations: [ComponentToTest],
providers: [
{
provide: ActivatedRoute,
useValue: {
paramMap: Observable.of({ get: (key) => 'value' })
}
}
]
});
对于任何对如何正确使用多个属性感兴趣的人,以下是定义模拟类的方法:
import { convertToParamMap } from '@angular/router';
import { Observable } from 'rxjs/Observable';
export class ActivatedRouteMock {
public paramMap = Observable.of(convertToParamMap({
testId: 'abc123',
anotherId: 'd31e8b48-7309-4c83-9884-4142efdf7271',
}));
}
通过这种方式,您可以订阅您的
paramMap
并检索多个值-在这种情况下,testId
和anotherId
修改上述Andrus的答案
对于RxJS 6+:
import { convertToParamMap } from '@angular/router';
import { of } from 'rxjs';
export class ActivatedRouteMock {
public paramMap = of(convertToParamMap({
testId: 'abc123',
anotherId: 'd31e8b48-7309-4c83-9884-4142efdf7271',
}));
}
在我的例子中,我必须创建一个新类来处理这种类型的测试,这个类将允许您处理快照、查询参数和参数
import { Params } from '@angular/router';
import { BehaviorSubject } from 'rxjs';
export class MockActivatedRoute {
private innerTestParams?: any;
private subject?: BehaviorSubject<any> = new BehaviorSubject(this.testParams);
params = this.subject.asObservable();
queryParams = this.subject.asObservable();
constructor(params?: Params) {
if (params) {
this.testParams = params;
} else {
this.testParams = {};
}
}
get testParams() {
return this.innerTestParams;
}
set testParams(params: {}) {
this.innerTestParams = params;
this.subject.next(params);
}
get snapshot() {
return { params: this.testParams, queryParams: this.testParams };
}
}
从'@angular/router'导入{Params};
从“rxjs”导入{BehaviorSubject};
导出类MockActivatedRoute{
私有innerTestParams?:任意;
private subject?:BehaviorSubject在最近的Angular版本中,项目的aot
设置在默认情况下是打开的(以便更好地进行编译时类型检查)。如果项目是这样,那么您可能至少需要删除ActivatedRoute和ActivatedRouteSnapshot的所有属性。类似于以下内容:
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Type } from '@angular/core';
import { Location } from '@angular/common';
import { MockPlatformLocation } from '@angular/common/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { ActivatedRoute, ActivatedRouteSnapshot, Params, ParamMap, convertToParamMap } from '@angular/router';
import { of, BehaviorSubject } from 'rxjs';
import { HeroDetailComponent } from './hero-detail.component';
import { Hero } from '../hero';
export class MockActivatedRouteSnapshot implements ActivatedRouteSnapshot {
private innerTestParams?: Params;
constructor(params?: Params) {
if (params) {
this.testParams = params;
} else {
this.testParams = null;
}
}
private get testParams() {
return this.innerTestParams;
}
private set testParams(params: Params) {
this.innerTestParams = params;
}
get paramMap() {
return convertToParamMap(this.testParams);
}
get queryParamMap() {
return this.paramMap;
}
get url() {
return null;
}
get fragment() {
return null;
}
get data() {
return null;
}
get outlet() {
return null;
}
get params() {
return this.innerTestParams;
}
get queryParams() {
return this.innerTestParams;
}
get component() {
return null;
}
get routeConfig() {
return null;
}
get root() {
return null;
}
get parent() {
return null;
}
get firstChild() {
return null;
}
get children() {
return null;
}
get pathFromRoot() {
return null;
}
}
export class MockActivatedRoute implements ActivatedRoute {
private innerTestParams?: Params;
private subject?: BehaviorSubject<Params> = new BehaviorSubject(this.testParams);
private paramMapSubject?: BehaviorSubject<ParamMap> = new BehaviorSubject(convertToParamMap(this.testParams));
constructor(params?: Params) {
if (params) {
this.testParams = params;
} else {
this.testParams = null;
}
}
private get testParams() {
return this.innerTestParams;
}
private set testParams(params: Params) {
this.innerTestParams = params;
this.subject.next(params);
this.paramMapSubject.next(convertToParamMap(params));
}
get snapshot() {
return new MockActivatedRouteSnapshot(this.testParams);
}
get params() {
return this.subject.asObservable();
}
get queryParams() {
return this.params;
}
get paramMap() {
return this.paramMapSubject.asObservable();
}
get queryParamMap() {
return this.paramMap;
}
get url() {
return null;
}
get fragment() {
return null;
}
get data() {
return null;
}
get outlet() {
return null;
}
get component() {
return null;
}
get routeConfig() {
return null;
}
get root() {
return null;
}
get parent() {
return null;
}
get firstChild() {
return null;
}
get children() {
return null;
}
get pathFromRoot() {
return null;
}
}
describe('HeroDetailComponent', () => {
let component: HeroDetailComponent;
let fixture: ComponentFixture<HeroDetailComponent>;
let httpMock: HttpTestingController;
let routeMock: MockActivatedRoute;
let initialMockParams: Params;
let locationMock: MockPlatformLocation;
beforeEach(async(() => {
initialMockParams = {id: 11};
routeMock = new MockActivatedRoute(initialMockParams);
locationMock = new MockPlatformLocation;
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule
],
declarations: [ HeroDetailComponent ],
providers: [
{
provide: ActivatedRoute, useValue: routeMock,
},
{
provide: Location, useValue: locationMock,
}
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeroDetailComponent);
component = fixture.componentInstance;
httpMock = TestBed.inject<HttpTestingController>(HttpTestingController as Type<HttpTestingController>);
fixture.detectChanges();
});
afterEach(() => {
httpMock.verify();
});
it('should be created', () => {
fixture.detectChanges();
expect(component).toBeTruthy();
const dummyHero: Hero = { id: 11, name: 'dummyHero' };
const req = httpMock.expectOne('api/details/11');
req.flush(dummyHero);
});
});
从'@angular/core/testing'导入{async,ComponentFixture,TestBed};
从'@angular/core'导入{Type};
从“@angular/common”导入{Location};
从“@angular/common/testing”导入{MockPlatformLocation};
从“@angular/common/http/testing”导入{HttpClientTestingModule,HttpTestingController};
从“@angular/router”导入{ActivatedRoute,ActivatedRouteSnapshot,Params,ParamMap,convertToParamMap};
从'rxjs'导入{of,BehaviorSubject};
从“./hero detail.component”导入{HeroDetailComponent};
从“../Hero”导入{Hero};
导出类MockActivatedRouteSnapshot实现ActivatedRouteSnapshot{
私有innerTestParams?:参数;
构造函数(参数?:参数){
如果(参数){
this.testParams=params;
}否则{
this.testParams=null;
}
}
private get testParams(){
返回this.innerTestParams;
}
私有集testParams(params:params){
this.innerTestParams=params;
}
获取参数映射(){
返回convertToParamMap(this.testParams);
}
获取queryParamMap(){
返回此.paramMap;
}
获取url(){
返回null;
}
获取片段(){
返回null;
}
获取数据(){
返回null;
}
获取出口(){
返回null;
}
获取参数(){
返回this.innerTestParams;
}
获取查询参数(){
返回this.innerTestParams;
}
获取组件(){
返回null;
}
获取routeConfig(){
返回null;
}
获取根(){
返回null;
}
获取父对象(){
返回null;
}
获取第一个孩子(){
返回null;
}
得到孩子{
返回null;
}
获取路径fromRoot(){
返回null;
}
}
导出类MockActivateRoute实现ActivateRoute{
私有innerTestParams?:参数;
私有主题?:BehaviorSubject=新的BehaviorSubject(this.testParams);
private paramMapSubject?:BehaviorSubject=新的BehaviorSubject(convertToParamMap(this.testParams));
构造函数(参数?:参数){
如果(参数){
this.testParams=params;
}否则{
this.testParams=null;
}
}
private get testParams(){
返回this.innerTestParams;
}
私有集testParams(params:params){
this.innerTestParams=params;
this.subject.next(params);
this.paramMapSubject.next(convertToParamMap(params));
}
获取快照(){
返回新的MockActivatedRouteSnapshot(this.testParams);
}
获取参数(){
返回此.subject.asObservable();
}
获取查询参数(){
返回此.params;
}
获取参数映射(){
返回此.parammappubject.asObservable();
}
获取queryParamMap(){
返回此.paramMap;
}
获取url(){
返回null;
}
获取片段(){
返回null;
}
获取数据(){
返回null;
}
获取出口(){
返回null;
}
获取组件(){
返回null;
}
获取routeConfig(){
返回null;
}
获取根(){
返回null;
}
获取父对象(){
返回null;
}
获取第一个孩子(){
返回null;
}
得到孩子{
返回null;
}
获取路径fromRoot(){
返回null;
}
}
描述('HeroDetailComponent',()=>{
let组件:HeroDetailComponent;
let夹具:组件夹具;
让httpock:HttpTestingController;
让routeMock:MockActivatedRoute;
让initialMockParams:Params;
let locationMock:MockPlatformLocation;
beforeach(异步(()=>{
initialMockParams={id:11};
routeMock=新的MockActivatedRoute(初始MockParams);
locationMock=新的MockPlatformLocation;
TestBed.configureTestingModule({
进口:[
HttpClientTestingModule
],
声明:[HeroDetailComponent],
供应商:[
{
提供:ActivatedRoute,使用值:routeMock,
},
{
提供:位置,使用值:locationMock,
}
]
})
.compileComponents();
}));
在每个之前(()=>{
fixture=TestBed.createComponent(HeroDetailComponent);
组件=fixture.componentInstance;
httpMock=TestBed.inject(类型为HttpTestingController);
fixture.detectChanges();
});
之后(()=>{
httpMock.verify();
});
它('应该创建',()=>{
fixture.detectChanges();
expect(component.toBeTruthy();
常数
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { Type } from '@angular/core';
import { Location } from '@angular/common';
import { MockPlatformLocation } from '@angular/common/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { ActivatedRoute, ActivatedRouteSnapshot, Params, ParamMap, convertToParamMap } from '@angular/router';
import { of, BehaviorSubject } from 'rxjs';
import { HeroDetailComponent } from './hero-detail.component';
import { Hero } from '../hero';
export class MockActivatedRouteSnapshot implements ActivatedRouteSnapshot {
private innerTestParams?: Params;
constructor(params?: Params) {
if (params) {
this.testParams = params;
} else {
this.testParams = null;
}
}
private get testParams() {
return this.innerTestParams;
}
private set testParams(params: Params) {
this.innerTestParams = params;
}
get paramMap() {
return convertToParamMap(this.testParams);
}
get queryParamMap() {
return this.paramMap;
}
get url() {
return null;
}
get fragment() {
return null;
}
get data() {
return null;
}
get outlet() {
return null;
}
get params() {
return this.innerTestParams;
}
get queryParams() {
return this.innerTestParams;
}
get component() {
return null;
}
get routeConfig() {
return null;
}
get root() {
return null;
}
get parent() {
return null;
}
get firstChild() {
return null;
}
get children() {
return null;
}
get pathFromRoot() {
return null;
}
}
export class MockActivatedRoute implements ActivatedRoute {
private innerTestParams?: Params;
private subject?: BehaviorSubject<Params> = new BehaviorSubject(this.testParams);
private paramMapSubject?: BehaviorSubject<ParamMap> = new BehaviorSubject(convertToParamMap(this.testParams));
constructor(params?: Params) {
if (params) {
this.testParams = params;
} else {
this.testParams = null;
}
}
private get testParams() {
return this.innerTestParams;
}
private set testParams(params: Params) {
this.innerTestParams = params;
this.subject.next(params);
this.paramMapSubject.next(convertToParamMap(params));
}
get snapshot() {
return new MockActivatedRouteSnapshot(this.testParams);
}
get params() {
return this.subject.asObservable();
}
get queryParams() {
return this.params;
}
get paramMap() {
return this.paramMapSubject.asObservable();
}
get queryParamMap() {
return this.paramMap;
}
get url() {
return null;
}
get fragment() {
return null;
}
get data() {
return null;
}
get outlet() {
return null;
}
get component() {
return null;
}
get routeConfig() {
return null;
}
get root() {
return null;
}
get parent() {
return null;
}
get firstChild() {
return null;
}
get children() {
return null;
}
get pathFromRoot() {
return null;
}
}
describe('HeroDetailComponent', () => {
let component: HeroDetailComponent;
let fixture: ComponentFixture<HeroDetailComponent>;
let httpMock: HttpTestingController;
let routeMock: MockActivatedRoute;
let initialMockParams: Params;
let locationMock: MockPlatformLocation;
beforeEach(async(() => {
initialMockParams = {id: 11};
routeMock = new MockActivatedRoute(initialMockParams);
locationMock = new MockPlatformLocation;
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule
],
declarations: [ HeroDetailComponent ],
providers: [
{
provide: ActivatedRoute, useValue: routeMock,
},
{
provide: Location, useValue: locationMock,
}
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HeroDetailComponent);
component = fixture.componentInstance;
httpMock = TestBed.inject<HttpTestingController>(HttpTestingController as Type<HttpTestingController>);
fixture.detectChanges();
});
afterEach(() => {
httpMock.verify();
});
it('should be created', () => {
fixture.detectChanges();
expect(component).toBeTruthy();
const dummyHero: Hero = { id: 11, name: 'dummyHero' };
const req = httpMock.expectOne('api/details/11');
req.flush(dummyHero);
});
});
providers: [{ provide: ActivatedRoute, useValue: { paramMap: new Subject() } }]
activatedRoute = TestBed.inject(ActivatedRoute);
activatedRoute.paramMap.next({ get: (key: string) => 'value1'});