You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 10:17:38