angular - Angular 测试 - 如何使用扩展基类测试数据服务
问题描述
我很难设置我的数据服务的测试,我正在尝试使用HttpClientTestingModule
这些文章中定义的测试 with the Angular HttpClient API,来自这个SO Question并且还尝试inject
了从这篇文章测试 HttpClient但我不能让它工作。
我相信我的问题来自这样一个事实,即我有一个DataService
使用 3 个服务提供商(HttpClient
、NGXLogger和TranslateService from ngx-translate
)的全局变量。然后我有多个数据服务,它们DataService
像这样扩展全局
@Injectable()
export class UserDataService extends DataService {
constructor(protected http: HttpClient, protected logger: NGXLogger, protected translate: TranslateService) {
super(http, logger, translate);
this.url = `api/users`;
}
getUsers(): Observable<Users[]> {
return super.getAll<User[]>(this.url);
}
如您所见,每个扩展数据服务(如UserDataServices
)都负责将 3 个必要的依赖项注入到super
调用中。
我正在尝试使用Jest
以下代码对我的测试进行编码
describe('User Data Service', () => {
let dataService: TemplateDataService;
let httpTestingController: HttpTestingController;
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
TranslateModule.forRoot(),
LoggerModule.forRoot({ level: NgxLoggerLevel.ERROR, serverLoggingUrl: 'api/logging', serverLogLevel: NgxLoggerLevel.ERROR }),
],
providers: [
UserDataService
]
});
dataService = TestBed.get(UserDataService);
httpTestingController = TestBed.get(HttpTestingController);
});
it('should return an Observable<User[]>', () => {
const dummyUsers = [
{ login: 'John' },
{ login: 'Doe' }
];
dataService.getAll().subscribe((users: User[]) => {
expect(users.length).toBe(2);
expect(users).toEqual(dummyUsers);
});
const req = httpTestingController.expectOne(`api/users`);
expect(req.request.method).toBe('GET');
req.flush(dummyUsers);
});
它不断抛出以下错误
Unexpected value 'HttpClientModule' imported by the module 'HttpClientTestingModule'. Please add a @NgModule annotation.
我也试过这段代码,但我得到了同样的错误
it(
'should get users',
inject(
[HttpTestingController, NGXLogger, TranslateService, DataService],
(
httpMocker: HttpTestingController,
logger: NGXLogger,
translate: TranslateService,
dataServicer: DataService
) => {
// ...our test logic here
}
)
);
我对单元测试相当陌生(我上周开始),我完全无法测试我的任何数据服务(从好的方面来说,我可以使用数据服务模拟测试组件,但我我也想测试这些数据服务)。
在技术方面,该项目使用Angular: ^7.2.10
和jest: ^23.6.0
.
编辑
我忘了提到它DataService
也是一个服务,我也尝试将它添加到providers
中,但beforeEach()
我仍然得到相同的错误(Unexpected value 'HttpClientModule'...
)。如下所示
beforeEach(() => {
TestBed.configureTestingModule({
imports: [
HttpClientTestingModule,
TranslateModule.forRoot(),
LoggerModule.forRoot({ level: NgxLoggerLevel.ERROR, serverLoggingUrl: 'api/logging', serverLogLevel: NgxLoggerLevel.ERROR }),
],
providers: [
DataService,
UserDataService
]
});
});
此外,为了更全面地了解DataService
,这里是它的精简版。
export class DataService {
constructor(protected http: HttpClient, protected logger: NGXLogger, protected translate: TranslateService) {}
get<T>(id?: string, options?: HttpOptions): Observable<T> {
const caller = findCaller(new Error());
const uriWithId = id ? `/${id}` : '';
const requestUrl = this.addGlobalQueryParams(`${this.url}${uriWithId}`);
this.logger.debug(`DataService - GET method [${caller}] - START - URL:: ${requestUrl}`);
return this.http.get<T>(requestUrl, options).pipe(map((response: any) => {
this.logger.debug(`DataService - GET method [${caller}] - END - URL:: ${requestUrl} - Response:: `, response);
return response;
}));
}
getAll<T>(url?: string, options?: HttpOptions): Observable<T> {
const caller = findCaller(new Error());
if (url) {
this.logger.debug(`DataService - POST method [${caller}] - START - URL:: `, url);
return this.http.post<T>(url).pipe(map((response: any) => {
this.logger.debug(`DataService - POST method [${caller}] - END - URL:: ${url} - Response:: `, response);
return response;
}));
}
}
}
编辑 2
我想我正在寻找的是如何对扩展类进行单元测试,这实际上是在 Angular 存储库中提出的,但从未得到回答和关闭,因为这不是问题,而是更多的问题。
解决方案
首先,您不需要在测试中执行以下操作。
providers: [
UserDataService
]
由于您正在测试UserDataService
自身,因此在设置 TestBed 后执行以下操作就足够了。
dataService = TestBed.inject(UserDataService); //TestBed.get(UserDataService);
要改变的另一件事是使您的基类可注入。
@Injectable()
export class DataService {...}
我知道这听起来很愚蠢,但显然角度 DI 似乎也需要它。
推荐阅读
- c++ - 如何在没有新班级多米诺骨牌效应的情况下创建新班级以造福后代
- android - 有没有办法在 Flutter 中创建嵌套抽屉?
- python - 如何将用户输入的姓名和年龄列表排序为具有相应姓名的平均年龄、最高和最低年龄?
- android - 如何更改 Xamarin 项目的 Android 主题?
- github - GitHub搜索GUI中单引号和双引号有什么区别
- laravel - 处理 Lumen API 内存耗尽错误的最佳方法是什么
- hyperledger-fabric - 错误:ID 为“$sysregistries”的集合中 ID 为“Asset:org.supplychain.food.model.LiveAsset”的对象不存在”
- javascript - jQuery .append() 和 .attr() 的这种组合可以被 XSS 攻击利用吗?
- c++ - 如何在我的进程中运行的二进制文件中注册 Op 和 Kernel?
- typescript - 打字稿如何克隆除一键外的对象