【发布时间】:2019-05-02 19:16:35
【问题描述】:
我的服务是一个单例,在它的构造函数中它调用一个函数来进行 API 调用。这在服务初始化时非常有用,因为它降低了调用这些应用程序启动 Api 所需的复杂性和导入。这使得服务独立,因为它不需要依赖AppComponent 来导入和调用 Api 函数。
在应用程序负载上实例化单例服务:app.module.ts
....
export class AppModule {
constructor(private applicationSettings: ApplicationSettings) {
}
}
...
服务:application-settings.ts
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
})
export class ApplicationSettings{
...
constructor( private httpClient: HttpClient ){
this.LoadSettings();
}
private LoadSettings() {
this.httpClient.get<any>(this.settingsApiUrl, { observe: 'response' })
.pipe(
retry(3)
).subscribe(
data => this.ApiSuccess(data),
error => this.ApiError(error)
);
}
...
}
单元测试:application-settings.spec.ts
import { ApplicationSettings } from './application-settings.service';
import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { environment } from '@environments/environment';
let applicationSettings;
let httpMock: HttpTestingController;
let settingsApiUrl = environment.ApplicationSettings;
describe('ApplicationSettings', () => {
beforeEach(() => {
TestBed.configureTestingModule({
providers: [
ApplicationSettings
],
imports: [
HttpClientTestingModule
]
});
});
beforeEach(() => {
applicationSettings = TestBed.get(ApplicationSettings);
httpMock = TestBed.get(HttpTestingController);
// Attempt to catch from constructor
httpMock.expectOne({
url: settingsApiUrl,
method: 'get'
}).flush({});
httpMock.verify();
});
describe('Tests To Pass', () => {
fit('should create the app', () => {
expect(applicationSettings).toBeDefined();
});
fit('should be successfull and call ApiSuccess', () => {
spyOn(applicationSettings, 'ApiSuccess');
httpMock.expectOne({
url: settingsApiUrl,
method: 'get'
}).flush({});
applicationSettings.LoadSettings();
expect(applicationSettings.ApiSuccess).toHaveBeenCalled();
});
...
});
});
在运行我的测试用例时,有时它们会正常工作,但 80% 的情况下它们会抛出错误。一个测试可能抛出 1,另一个 3,另一个可能是 5(不一定按这个顺序:
[object ErrorEvent] thrown
[object ErrorEvent] thrown
[object ErrorEvent] thrown
它会说:
Error: Expected one matching request for criteria "Match method: get, URL: //localhost/api/appSettings", found none.
如果我删除主BeforeEach() 中的httpMock.expectOne(我在该行上有注释,表明试图捕获构造函数)。那么每次测试都会出现这个错误:
Expected no open requests, found 1: GET //localhost/...
我 100% 肯定它与构造函数中的 Api 调用有关,据我所知,它创建的每个测试并使用 AppSettings 服务的新实例,这反过来会触发 LoadSettings API 函数。
和在我将调用移至构造函数之前一样,所有测试都通过了。
【问题讨论】:
标签: angular unit-testing jasmine karma-jasmine angular-services