Typescript - Angular 测试,如何使用 ngOnInit 中的参数处理 http 请求?
Typescript - Angular testing, how to handle http request with parameters that is inside of ngOnInit?
我有一个模态组件,它从外部获取输入,打开后,确实会向服务器发送请求以获取数据。获取数据后,它被分配给一个 public 变量并用于显示数据。我如何为它编写测试?我需要模拟 HttpClient 吗?还是我必须提供所有 @Input 元素,然后像往常一样发出请求?但是在那种情况下,我需要有真实的数据供后端在数据库中查找。
我尝试用谷歌搜索这个特定问题,但似乎找不到任何东西。我确实找到了如何模拟请求,但当它们在 ngOnInit() 中时却找不到。我将在下面添加所有必要的代码。
组件:
enum Nav {
General = 'General',
SSL = 'SSL',
Routes = 'Routes',
Statistics = 'Statistics'
};
@Component({
selector: 'app-mod-route-properties',
templateUrl: './mod-route-properties.component.html',
styleUrls: ['./mod-route-properties.component.scss']
})
export class ModRoutePropertiesComponent implements OnInit {
@Input()
title: string;
@Input()
resourceAddress: ResourceAddress;
@Input()
wgsKey: string;
public emsRouteInfoData: EmsRouteInfoData;
public sideMenuItems = Object.values(Nav);
public active: string;
Nav = Nav;
constructor(
private modRoutePropertiesService: ModRoutePropertiesService
) {
}
ngOnInit() {
this.active = Nav.General;
this.modRoutePropertiesService.getRouteProperties(this.resourceAddress, this.wgsKey).subscribe((res: EmsRouteInfoData) => {
this.emsRouteInfoData = res;
}, err => {
console.log(err);
});
}
}
服务:
@Injectable()
export class ModRoutePropertiesService {
constructor(
private urlService: UrlService,
private serverSettingsService: ServerSettingsService,
private http: HttpClient
) { }
public getRouteProperties(resourceAddress: ResourceAddress, wgsKey: string) {
let token = this.urlService.getTokenByKey(wgsKey);
let url = this.serverSettingsService.getRequestUrl('/route/properties');
let headers = { 'x-access-token': token };
let params = {
manager: resourceAddress.manager,
node: resourceAddress.node,
qmgr: resourceAddress.qmgr,
route: resourceAddress.objectName
};
const rq = { headers: new HttpHeaders(headers), params: params };
return this.http.get<EmsRouteInfoData>(url, rq);
}
}
自我测试:
describe('ModRoutePropertiesComponent', () => {
let component: ModRoutePropertiesComponent;
let fixture: ComponentFixture<ModRoutePropertiesComponent>;
let httpMock: HttpTestingController;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
FormsModule,
HttpClientTestingModule,
NgbModule.forRoot(),
RouterModule
],
declarations: [
AppComponent,
ModRoutePropertiesComponent,
ModalTitleComponent,
ModRoutePropertiesGeneralComponent,
ModRoutePropertiesSslComponent,
ModRoutePropertiesRoutesComponent,
ModRoutePropertiesStatisticsComponent,
ModRoutePropertiesRouteSelectorComponent
],
providers: [
ModRoutePropertiesService,
UrlService,
TabsService,
{
provide: Router,
useClass: class { navigate = jasmine.createSpy('tab'); }
},
NgbActiveModal,
ServerSettingsService,
ModErrorsDisplayService,
ModalWindowService,
LoadingIndicatorService
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ModRoutePropertiesComponent);
component = fixture.componentInstance;
httpMock = TestBed.get(HttpTestingController);
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it(`should init 'active'`, () => {
expect(component.active).toBeDefined();
expect(component.active).toEqual(component.Nav.General);
});
it(`should have initialized 'emsRouteInfoData'`, async(() => {
expect(component.emsRouteInfoData).toBeDefined();
}));
});
我确实找到了解决方案。因此,为了测试 ngOnInit
方法内部的请求调用,您需要在调用 ngOnInit
之前监视该特定请求函数。与 spyOn(service, 'function').and.returnValue(Observable.of(object))
一起模拟请求调用和 returns 您指定的数据。
为此,我在 beforeEach()
测试存根上删除了 fixture.detectChanges()
。 detechChanges()
确实会触发组件的更改检测周期。之后,这就是我的 beforeEach()
的样子:
beforeEach(() => {
fixture = TestBed.createComponent(ModRoutePropertiesComponent);
component = fixture.componentInstance;
resourceAddress = new ResourceAddress();
resourceAddress.node = 'Node';
resourceAddress.manager = 'MANAGER';
resourceAddress.qmgr = 'T1';
resourceAddress.objectName = 'TestRoute';
// setting inputs
component.resourceAddress = resourceAddress;
component.title = title;
component.wgsKey = wgsKey;
});
之后,我将 detectChanges()
移动到特定的测试用例,在我模拟对所需函数的调用后 getRouteProperties
。
it(`should have initialized 'emsRouteInfoData'`, async(() => {
// needs 'Observable.of()' to simulate real Observable and subscription to it
spyOn(service, 'getRouteProperties').and.returnValue(Observable.of(dummyRoute));
// start ngOnInit
fixture.detectChanges();
expect(service.getRouteProperties).toHaveBeenCalled();
expect(component.emsRouteInfoData).toBeDefined();
}));
我有一个模态组件,它从外部获取输入,打开后,确实会向服务器发送请求以获取数据。获取数据后,它被分配给一个 public 变量并用于显示数据。我如何为它编写测试?我需要模拟 HttpClient 吗?还是我必须提供所有 @Input 元素,然后像往常一样发出请求?但是在那种情况下,我需要有真实的数据供后端在数据库中查找。
我尝试用谷歌搜索这个特定问题,但似乎找不到任何东西。我确实找到了如何模拟请求,但当它们在 ngOnInit() 中时却找不到。我将在下面添加所有必要的代码。
组件:
enum Nav {
General = 'General',
SSL = 'SSL',
Routes = 'Routes',
Statistics = 'Statistics'
};
@Component({
selector: 'app-mod-route-properties',
templateUrl: './mod-route-properties.component.html',
styleUrls: ['./mod-route-properties.component.scss']
})
export class ModRoutePropertiesComponent implements OnInit {
@Input()
title: string;
@Input()
resourceAddress: ResourceAddress;
@Input()
wgsKey: string;
public emsRouteInfoData: EmsRouteInfoData;
public sideMenuItems = Object.values(Nav);
public active: string;
Nav = Nav;
constructor(
private modRoutePropertiesService: ModRoutePropertiesService
) {
}
ngOnInit() {
this.active = Nav.General;
this.modRoutePropertiesService.getRouteProperties(this.resourceAddress, this.wgsKey).subscribe((res: EmsRouteInfoData) => {
this.emsRouteInfoData = res;
}, err => {
console.log(err);
});
}
}
服务:
@Injectable()
export class ModRoutePropertiesService {
constructor(
private urlService: UrlService,
private serverSettingsService: ServerSettingsService,
private http: HttpClient
) { }
public getRouteProperties(resourceAddress: ResourceAddress, wgsKey: string) {
let token = this.urlService.getTokenByKey(wgsKey);
let url = this.serverSettingsService.getRequestUrl('/route/properties');
let headers = { 'x-access-token': token };
let params = {
manager: resourceAddress.manager,
node: resourceAddress.node,
qmgr: resourceAddress.qmgr,
route: resourceAddress.objectName
};
const rq = { headers: new HttpHeaders(headers), params: params };
return this.http.get<EmsRouteInfoData>(url, rq);
}
}
自我测试:
describe('ModRoutePropertiesComponent', () => {
let component: ModRoutePropertiesComponent;
let fixture: ComponentFixture<ModRoutePropertiesComponent>;
let httpMock: HttpTestingController;
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
FormsModule,
HttpClientTestingModule,
NgbModule.forRoot(),
RouterModule
],
declarations: [
AppComponent,
ModRoutePropertiesComponent,
ModalTitleComponent,
ModRoutePropertiesGeneralComponent,
ModRoutePropertiesSslComponent,
ModRoutePropertiesRoutesComponent,
ModRoutePropertiesStatisticsComponent,
ModRoutePropertiesRouteSelectorComponent
],
providers: [
ModRoutePropertiesService,
UrlService,
TabsService,
{
provide: Router,
useClass: class { navigate = jasmine.createSpy('tab'); }
},
NgbActiveModal,
ServerSettingsService,
ModErrorsDisplayService,
ModalWindowService,
LoadingIndicatorService
]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ModRoutePropertiesComponent);
component = fixture.componentInstance;
httpMock = TestBed.get(HttpTestingController);
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
it(`should init 'active'`, () => {
expect(component.active).toBeDefined();
expect(component.active).toEqual(component.Nav.General);
});
it(`should have initialized 'emsRouteInfoData'`, async(() => {
expect(component.emsRouteInfoData).toBeDefined();
}));
});
我确实找到了解决方案。因此,为了测试 ngOnInit
方法内部的请求调用,您需要在调用 ngOnInit
之前监视该特定请求函数。与 spyOn(service, 'function').and.returnValue(Observable.of(object))
一起模拟请求调用和 returns 您指定的数据。
为此,我在 beforeEach()
测试存根上删除了 fixture.detectChanges()
。 detechChanges()
确实会触发组件的更改检测周期。之后,这就是我的 beforeEach()
的样子:
beforeEach(() => {
fixture = TestBed.createComponent(ModRoutePropertiesComponent);
component = fixture.componentInstance;
resourceAddress = new ResourceAddress();
resourceAddress.node = 'Node';
resourceAddress.manager = 'MANAGER';
resourceAddress.qmgr = 'T1';
resourceAddress.objectName = 'TestRoute';
// setting inputs
component.resourceAddress = resourceAddress;
component.title = title;
component.wgsKey = wgsKey;
});
之后,我将 detectChanges()
移动到特定的测试用例,在我模拟对所需函数的调用后 getRouteProperties
。
it(`should have initialized 'emsRouteInfoData'`, async(() => {
// needs 'Observable.of()' to simulate real Observable and subscription to it
spyOn(service, 'getRouteProperties').and.returnValue(Observable.of(dummyRoute));
// start ngOnInit
fixture.detectChanges();
expect(service.getRouteProperties).toHaveBeenCalled();
expect(component.emsRouteInfoData).toBeDefined();
}));