Мой сервис одноэлементный, и в своем конструкторе он вызывает функцию для вызова API.Это прекрасно работает, когда служба инициализируется, так как снижает сложность и импорт, необходимый для вызова этих приложений, запускает API.Кроме того, это делает службу независимой, поскольку ей не нужно полагаться на, скажем, AppComponent
для импорта и вызова функций Api.
Создание службы Singleton при загрузке приложения: 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.
Если я удаляю httpMock.expectOne
в основном BeforeEach()
(у меня есть комментарий к этой строке, указывающий на попытку перехватить конструктор). Затем каждый тест будет проходить через эту ошибку:
Expected no open requests, found 1: GET //localhost/...
Я на 100% уверен, что это связано с APIвызовите конструктор, насколько мне известно, каждый создаваемый им тест и использует новый экземпляр службы AppSettings, который, в свою очередь, вызовет функцию API LoadSettings.
Как и прежде, чем я переместил вызов в конструктор, всеиспытания проходили.