我有一项服务可以执行以下操作:
updateProperties(properties: any) {
return this.http.put(environment.adminApiURLPrefix+'api/v1/properties', properties);
}
在我的组件中,我有两个对象:providers 和providerProperties。 Providers 包含 API 提供者及其状态的键值对,而providerProperties 是从 API 返回的实际响应(必须存储,因为任何后续请求都需要整个对象)。
import { Component, OnInit } from '@angular/core';
import { ProviderService } from '../../services/provider.service';
import { Status } from 'src/app/models/status.enum';
import { AlertService } from 'src/app/services/alert.service';
@Component({
selector: 'app-providers',
templateUrl: './providers.component.html',
styleUrls: ['./providers.component.scss']
})
export class ProvidersComponent implements OnInit {
providers: any;
providerProperties: any;
status: Status;
constructor(private providerService: ProviderService, private alertService: AlertService) {
this.providers = {
'API1': false,
'API2': false,
'API3': false
}
this.status = Status.Loading;
}
ngOnInit() {
this.providerService.getProperties().subscribe((response: any) => {
this.setProviderValues(response);
this.status = Status.Ready;
},
error => {
this.alertService.error('Error');
this.status = Status.Error;
})
}
setProviderValues(response: any) {
this.providerProperties = response;
Object.keys(this.providers).forEach(key => {
let providerStatus: string = this.providerProperties[key.toLowerCase() + '.enabled'];
if(providerStatus == 'true' || providerStatus == 'false') {
this.providers[key] = providerStatus == 'true' ? true : false;
} else {
this.alertService.error('Error.');
this.status = Status.Error;
return;
}
});
}
changeProviderProperty(provider: string, isEnabled: boolean) {
let providerKey: string = this.providerDisplayNameToPropertyKey(provider);
let tempProviderProperties = Object.assign({}, this.providerProperties);
tempProviderProperties[providerKey] = isEnabled ? true : false;
this.providerService.updateProperties(tempProviderProperties).subscribe(
response => {
this.setProviderValues(response);
this.alertService.success('Successfully '+ (isEnabled ? 'Enabled ' : 'Disabled ') + provider);
},
err => {
if(err['status'] == 0) {
this.alertService.error('Error');
} else {
let errorArray = err['error']['Errors']['Error'];
for(let errorKey in errorArray) {
let errorValue = errorArray[errorKey];
this.alertService.error('Error Updating Properties: ' + errorValue['ReasonCode'] + ' ' + errorValue['Description']);
}
}
}
)
}
providerDisplayNameToPropertyKey(provider: string) {
return provider.toLowerCase() + '.enabled';
}
}
我有以下测试:
import { async, ComponentFixture, TestBed, fakeAsync, tick } from '@angular/core/testing';
import { HttpClientTestingModule } from '@angular/common/http/testing';
import { ProvidersComponent } from './providers.component';
import { ProviderService } from 'src/app/services/provider.service';
import { of, Observable, throwError } from 'rxjs';
import { AlertComponent } from '../shared/alert/alert.component';
import { RouterTestingModule } from '@angular/router/testing';
import { AlertService } from 'src/app/services/alert.service';
import { HttpErrorResponse } from '@angular/common/http';
describe('ProvidersComponent', () => {
let component: ProvidersComponent;
let providerService: ProviderService;
let alertService: AlertService;
let fixture: ComponentFixture<ProvidersComponent>;
let getPropertiesSpy: jasmine.Spy<() => Observable<String>>;
let changeProviderPropertySpy: jasmine.Spy<(provider: string, isEnabled: boolean) => Promise<void>>;
let providerProperties:any;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
ProvidersComponent,
AlertComponent
],
imports: [
HttpClientTestingModule,
RouterTestingModule
],
providers: [
ProviderService,
AlertService
]
})
.compileComponents();
}));
beforeEach(() => {
providerService = TestBed.get(ProviderService);
alertService = TestBed.get(AlertService);
fixture = TestBed.createComponent(ProvidersComponent);
providerProperties = {
'api1.enabled': 'true',
'api2.enabled': 'true',
'api3.enabled': 'false',
};
component = fixture.componentInstance;
component.providers = {
'API1': false,
'API2': false,
'API3': false
};
getPropertiesSpy = spyOn(providerService, 'getProperties').and.callFake(() => {
return of(providerProperties);
});
changeProviderPropertySpy = spyOn(component, 'changeProviderProperty');
fixture.detectChanges();
});
it('should enable provider', fakeAsync(() => {
spyOn(providerService, 'updateProperties').and.returnValue(of({
'api1.enabled': 'true',
'api2.enabled': 'false',
'api3.enabled': 'false'
}));
component.changeProviderProperty('API1', true);
fixture.detectChanges();
expect(component.providers['API1']).toEqual(true);
}));
});
由于某种原因,对象的状态不会改变。我相当确定可观察的内容没有被订阅,或者我没有等待响应。
更新 在我调用changeProviderProperties之后监视提供者服务并检查它是否被调用后,结果发现它从未被调用过。
更新2 监视了providerDisplayNameToPropertyKey方法,发现无论出于什么原因它都没有被调用。
最佳答案
方法component.changeProviderProperty
包含异步代码。因为您知道这一点,所以您正在 fakeAsync
区域中运行测试。您缺少的是对 tick
的调用,它模拟 fakeAsync
区域中计时器的异步时间流逝。
it('should enable provider', fakeAsync(() => {
...
component.changeProviderProperty('API1', true);
tick();
...
}));
关于javascript - 测试可观察回调以更改对象状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59397755/