Angular 12单元测试HTTP请求查询参数被拆分问题
问题根源
Angular的HttpClient.get()方法的params参数不支持直接传入字符串格式的查询参数(如'page=1')。当你传入字符串时,它会被当作字符数组解析:每个字符的索引作为参数名,字符本身作为参数值,最终就出现了0=p&1=a&2=g&3=e&4==&5=1这种异常参数格式。同时测试代码里expectOne('host/foo/bar')匹配的是无参数URL,但实际请求带了异常参数,因此报错找不到匹配请求。
解决方案
1. 修正服务端请求代码
有两种可行修改方式:
方式一:传入键值对对象(推荐)
调整方法入参为键值对对象,直接传给params:
consumeGetPatientsToReconcile(query: { [key: string]: string }) { const host = this.appConfigService.apiBaseUrl; const url = `${host}/foo/bar`; const obs = this.http.get( url, { params: query } ); return obs.pipe(tap((data) => this.reconcileMainService.setReconcileData(data) )); }
方式二:将字符串转为HttpParams对象
若必须保留字符串格式入参,手动将字符串转为HttpParams实例(需先导入HttpParams):
import { HttpParams } from '@angular/common/http'; consumeGetPatientsToReconcile(query: string) { const host = this.appConfigService.apiBaseUrl; const url = `${host}/foo/bar`; const params = new HttpParams({ fromString: query }); const obs = this.http.get( url, { params } ); return obs.pipe(tap((data) => this.reconcileMainService.setReconcileData(data) )); }
2. 修正单元测试代码
对应服务修改,调整测试逻辑:
对应方式一的测试代码
调用方法时传入键值对,修正expectOne的匹配规则,正常获取参数:
it('should consume patients reconcile api', () => { service.consumeGetPatientsToReconcile({ page: '1' }).subscribe(); // 匹配带正确参数的URL,或用匹配函数更灵活 const req = httpTestingController.expectOne('host/foo/bar?page=1'); const pageValue = req.request.params.get('page'); console.log(pageValue); // 输出 '1' httpTestingController.verify(); });
对应方式二的测试代码
若服务用字符串转HttpParams,调用时传'page=1',同样修正匹配URL:
it('should consume patients reconcile api', () => { service.consumeGetPatientsToReconcile('page=1').subscribe(); const req = httpTestingController.expectOne('host/foo/bar?page=1'); const pageValue = req.request.params.get('page'); console.log(pageValue); // 输出 '1' httpTestingController.verify(); });
也可以用匹配函数替代硬拼URL,更健壮:
const req = httpTestingController.expectOne((request) => { return request.url === 'host/foo/bar' && request.params.get('page') === '1'; });
内容的提问来源于stack exchange,提问作者dman
相关产品推荐
相关产品推荐

