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

Angular 错误处理方法handleError的单元测试用例编写咨询

Angular handleError 方法单元测试实现方案

我们基于Angular官方提供的HttpClientTestingModule来模拟HTTP请求,覆盖handleError的两个分支(客户端/网络错误、后端返回错误码),同时验证返回错误信息是否符合预期。

前置配置

首先配置测试床,导入依赖并模拟外部服务:

import { TestBed } from '@angular/core/testing';
import { HttpClientTestingModule, HttpTestingController } from '@angular/common/http/testing';
import { HttpErrorResponse } from '@angular/common/http';
import { YourService } from './your-service.service'; // 替换为你自己的服务类路径
import { ConfigManagerService } from './config-manager.service'; // 替换为ConfigManagerService的实际路径

// 模拟依赖的ConfigManagerService
class MockConfigManagerService {
  statesApiUrl = 'https://test-api.com/states';
}

describe('YourService', () => {
  let service: YourService;
  let httpTestingController: HttpTestingController;
  // 劫持console.error避免测试输出冗余日志,同时验证日志输出是否正确
  let consoleErrorSpy: jasmine.Spy;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientTestingModule],
      providers: [
        YourService,
        { provide: ConfigManagerService, useClass: MockConfigManagerService }
      ]
    });
    service = TestBed.inject(YourService);
    httpTestingController = TestBed.inject(HttpTestingController);
    consoleErrorSpy = spyOn(console, 'error');
  });

  afterEach(() => {
    // 验证所有预期的请求都已处理,没有多余请求
    httpTestingController.verify();
  });

如果你使用Jest作为测试框架,仅需将consoleErrorSpy的类型jasmine.Spy修改为jest.Spy即可,其余逻辑完全通用。

测试用例1:覆盖后端返回错误码分支

通过模拟后端返回非2xx状态码,触发handleError的服务端错误分支:

it('should handle backend error correctly when calling getStates', (done) => {
    const testCountryId = 1;
    const mockStatusCode = 500;
    const mockErrorBody = 'Database connection failed';

    service.getStates(testCountryId).subscribe({
      next: () => fail('请求预期会失败,不应进入next回调'),
      error: (returnedError) => {
        // 验证返回的用户提示符合预期
        expect(returnedError).toBe('Value list currently not available.');
        // 验证错误日志输出正确
        expect(consoleErrorSpy).toHaveBeenCalledWith(`Backend returned code ${mockStatusCode}, body was: ${mockErrorBody}`);
        done();
      }
    });

    // 匹配发出的请求,返回模拟错误
    const req = httpTestingController.expectOne(`${MockConfigManagerService.prototype.statesApiUrl}/${testCountryId}`);
    req.flush(mockErrorBody, { status: mockStatusCode, statusText: 'Internal Server Error' });
  });

测试用例2:覆盖客户端/网络错误分支

通过模拟网络异常,触发handleError的客户端错误分支:

it('should handle client network error correctly when calling getStates', (done) => {
    const testCountryId = 1;
    const mockNetworkError = new ErrorEvent('ConnectionError', {
      message: 'Failed to connect to remote server'
    });

    service.getStates(testCountryId).subscribe({
      next: () => fail('请求预期会失败,不应进入next回调'),
      error: (returnedError) => {
        expect(returnedError).toBe('Value list currently not available.');
        expect(consoleErrorSpy).toHaveBeenCalledWith('An error occurred:', mockNetworkError.message);
        done();
      }
    });

    const req = httpTestingController.expectOne(`${MockConfigManagerService.prototype.statesApiUrl}/${testCountryId}`);
    // 触发客户端网络错误
    req.error(mockNetworkError);
  });
});

可选:单独测试handleError方法

如果需要直接对handleError做单元测试,不需要走getStates调用链路,可以补充以下用例:

it('handleError should return correct user message for client error', () => {
  const clientError = new HttpErrorResponse({
    error: new ErrorEvent('TestError', { message: 'Client side test error' })
  });

  service.handleError(clientError).subscribe({
    error: (err) => {
      expect(err).toBe('Value list currently not available.');
      expect(consoleErrorSpy).toHaveBeenCalledWith('An error occurred:', 'Client side test error');
    }
  });
});

it('handleError should return correct user message for backend error', () => {
  const backendError = new HttpErrorResponse({
    status: 404,
    error: 'Resource not found'
  });

  service.handleError(backendError).subscribe({
    error: (err) => {
      expect(err).toBe('Value list currently not available.');
      expect(consoleErrorSpy).toHaveBeenCalledWith('Backend returned code 404, body was: Resource not found');
    }
  });
});

以上用例可以100%覆盖handleError的所有代码分支,同时验证日志输出和返回值的正确性。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 16:24:03