问题描述
我是使用 Karma 进行 Angular 测试的新手,我不了解如何正确测试服务。 假设我有这项服务需要测试:
@Injectable()
export class MyService {
constructor(private httpService: HttpService) { }
//methods to test
}
这是我的测试课:
describe('MyService',() => {
let service: MyService;
beforeEach(async(() => {
Testbed.configureTestingModule({
providers: [MyService],}).compileComponents();
service = Testbed.get(MyService);
}));
});
当我运行 ng test 时,它给出了错误 NullInjectorError: No provider for HttpService!
。
所以我在测试类中将 HttpService 添加到 providers 数组中,这样:
describe('MyService',() => {
let service: MyService;
beforeEach(async(() => {
Testbed.configureTestingModule({
providers: [MyService,HttpService],}).compileComponents();
service = Testbed.get(MyService);
}));
});
HttpService 是这样的:
@Injectable()
export class HttpService{
constructor(private httpService: HttpClient) { }
}
所以现在我收到错误 NullInjectorError: No provider for HttpClient!
。 (HttpClient 来自@angular/common/http)。
如果我将 HttpClient 添加到测试类中的 providers 数组,那么对于 HttpClient 构造函数中的所有服务/类,我都会收到相同的错误,依此类推。什么是实例化服务的正确方法,而不必添加每个提供者,从而导致潜在的无限提供者?
解决方法
在您的测试平台配置中,导入 HttpClientTestingModule
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [HttpClientTestingModule],providers: [MyService,HttpService],}).compileComponents();
service = TestBed.get(MyService);
}));
你也可以考虑
-
将
TestBed.get(MyService);
更改为TestBed.inject(MyService);
作为TestBed.get(...)
已弃用 What's the difference between TestBed.get and new Service(...dependencies) -
将
async
更改为waitForAsync
作为async
已弃用 When to use waitForAsync in angular
您应该使用 HttpClientTestingModule
并通过 HttpTestingController
和 flush
方法模拟数据。这是一个关于我如何测试服务的 Angular 11 和 jasmine 3.6.0 示例。希望能帮到你:
// Dependencies
import { TestBed,waitForAsync } from '@angular/core/testing';
import { HttpClientTestingModule,HttpTestingController } from '@angular/common/http/testing';
// Assets
import { ExampleService } from './api/example.service';
describe('*[Example Service]: -----------------------------------------',() => {
let httpTestingController: HttpTestingController;
let service: ExampleService;
beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule
]
}).compileComponents();
httpTestingController = TestBed.inject(HttpTestingController);
service = TestBed.inject(ExampleService);
}));
it('1). should get data from GET service',waitForAsync( () => {
// Arrange
const expectedData: string[] = ['data1','data2'];
let apiError,apiData;
// Action
service.getData().subscribe(response => {
apiData = response;
},error => {
apiError = error;
});
const request = httpTestingController.expectOne(`http://localhost:3000/example`);
request.flush(expectedData);
// Assert
expect(apiData.length).toEqual(2);
expect(apiError).toBeUndefined();
}));
});