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

Angular 4组件内直接调用http.get的测试方法咨询

搞定Angular 4组件HTTP调用的测试问题

嘿,我来帮你解决这个测试的问题!首先提个小细节:你组件里的crispList其实是个Observable,不是直接的数组数据——因为你把http.get经过map处理后的Observable直接赋值给它了。这意味着测试时我们得订阅它才能拿到实际值来做断言。

接下来咱们一步步完善你的测试代码,同时搞定两个测试目标:验证HTTP调用确实执行了,以及crispList的值和模拟数据一致。


核心思路梳理

我们已经用了MockBackend来模拟HTTP请求,接下来要做的就是:

  1. 在Mock的连接回调里标记请求是否触发,同时验证请求URL正确
  2. 订阅crispList这个Observable,在回调里断言数据是否符合预期

修改后的完整测试代码

describe('CrispFlavourComponent', () => {
  let backend: MockBackend;
  let componentFixture: ComponentFixture<CrispFlavourComponent>;
  let component: CrispFlavourComponent;
  const mockResponse = {
    walkers: {
      crisps: [
        { name: 'Salt & Vinegar' },
        { name: 'Cheese & Onion' }
      ]
    }
  };
  let isHttpCalled = false; // 用来标记HTTP请求是否被触发

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        RouterTestingModule.withRoutes([
          { path: '**', component: DummyComponent }
        ]),
        TranslateI18NextTestingModule.forRoot()
      ],
      declarations: [
        DummyComponent,
        CrispFlavorComponent
      ],
      schemas: [CUSTOM_ELEMENTS_SCHEMA],
      providers: [
        MockBackend,
        BaseRequestOptions,
        {
          provide: Http,
          useFactory: (backendInstance: MockBackend, defaultOptions: BaseRequestOptions) => {
            return new Http(backendInstance, defaultOptions);
          },
          deps: [MockBackend, BaseRequestOptions]
        }
      ]
    });

    TestBed.compileComponents().then(() => {
      componentFixture = TestBed.createComponent(CrispFlavourComponent);
      component = componentFixture.componentInstance; // 提前拿到组件实例,方便后续操作
    });
  }));

  beforeEach(inject([MockBackend], (mockBackend: MockBackend) => {
    backend = mockBackend;
    isHttpCalled = false; // 每次测试前重置标记
    backend.connections.subscribe((connection: MockConnection) => {
      // 验证请求的URL是不是我们要的那个
      expect(connection.request.url).toBe('path/to/crisp-flavors.json');
      isHttpCalled = true; // 标记请求已触发
      
      // 返回模拟的响应数据
      const options = new ResponseOptions({
        status: 200,
        body: JSON.stringify(mockResponse)
      });
      connection.mockRespond(new Response(options));
    });
  }));

  it('should load crisp flavors and verify HTTP call is made', (done) => {
    component.ngOnInit();
    
    // 订阅crispList,拿到数据后做断言
    component.crispList.subscribe((crisps) => {
      // 验证返回的列表和我们的模拟数据一致
      expect(crisps).toEqual(mockResponse.walkers.crisps);
      // 验证HTTP请求确实被执行了
      expect(isHttpCalled).toBe(true);
      done(); // 告诉Jasmine异步测试完成,不用再等啦
    });
  });
});

关键改动说明

  1. 提前获取组件实例:把component实例提前拿到,这样调用ngOnInit和访问crispList都更方便。
  2. HTTP请求标记:用isHttpCalled变量记录请求是否触发,再结合URL验证,确保调用的是正确的接口。
  3. 异步测试处理:因为HTTP请求是异步的,所以要用done回调告诉Jasmine等我们的订阅回调执行完再结束测试,不然测试会提前跑完,断言根本没执行。
  4. 数据断言:在订阅的回调里直接对比返回的crisps和模拟数据,确保我们的map处理逻辑是对的。

额外小建议:如果想让crispList是实际数组

如果你希望组件里的crispList是直接的数组(不是Observable),可以修改组件代码,在ngOnInit里订阅HTTP请求并赋值:

public crispList: any[] = []; // 改成数组类型
public ngOnInit() {
  this.http.get('path/to/crisp-flavors.json').map((res: any) => {
    const respJson = res.json();
    return respJson.walkers.crisps;
  }).subscribe((crisps) => {
    this.crispList = crisps;
  });
}

这种情况下,测试可以用fixture.whenStable()来等待异步操作完成:

it('should load the list of Crisp Flavors', async(() => {
  component.ngOnInit();
  componentFixture.whenStable().then(() => {
    expect(component.crispList).toEqual(mockResponse.walkers.crisps);
    expect(isHttpCalled).toBe(true);
  });
}));

这样就能完美满足你的两个测试需求啦!

内容的提问来源于stack exchange,提问作者Mark Sandman

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 08:18:16