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

在Jasmine与RxJS中模拟HTTP错误Observable的测试问题

问题描述

在Jasmine测试中,组件的服务调用错误回调无法正确接收HttpErrorResponse,测试时err输出为空字符串,导致foo未被设为true,测试失败。生产环境代码运行正常。

相关代码

component.ts

public thingThatCallsService() {
    this.foo = false;
    this.service.bar()
        .subscribe(
            (res) => {log(res)},
            (err) => {
                log(err) // 测试期间输出空字符串
                if (err.status === 400) this.foo = true;
            }
        );
}

mockService.ts(测试用模拟服务)

public bar() {
    return of(new HttpResponse());
}

test.ts

it("sets foo to true if bar returns an error", fakeAsync(() => {
    spyOn(service, "bar").and.returnValue(
        throwError(() => new HttpErrorResponse({status: 400}))
    );
    component.thingThatCallsService();
    tick();
    componentFixture.detectChanges();
    expect(service.bar).toHaveBeenCalled();
    expect(component.foo).toBeTrue(); // 测试失败
}))
解决方案

1. 对齐RxJS版本的throwError用法

  • RxJS 7+:工厂函数写法正确,但需确保导入的throwError来自rxjs
  • RxJS 6及以下:直接传入错误对象,无需工厂函数:
    throwError(new HttpErrorResponse({status: 400}))
    

2. 验证Spy的返回值

在测试中添加临时订阅,确认Spy返回的Observable确实抛出正确的错误:

const spy = spyOn(service, "bar").and.returnValue(
    throwError(() => new HttpErrorResponse({status: 400}))
);
// 临时订阅验证错误
spy.calls.mostRecent().returnValue.subscribe({
    error: err => console.log(err.status) // 应输出400
});

3. 完善HttpErrorResponse构造参数

补充必要字段,避免对象序列化异常:

throwError(() => new HttpErrorResponse({
    status: 400,
    statusText: 'Bad Request',
    error: { message: 'Invalid input' },
    url: '/api/bar'
}))

4. 使用defer确保错误在订阅时抛出

用defer包装错误流,确保Observable在订阅阶段才创建错误:

import { defer, throwError } from 'rxjs';

spyOn(service, "bar").and.returnValue(
    defer(() => throwError(() => new HttpErrorResponse({status: 400})))
);

5. 排查服务流中的错误吞掉情况

检查服务的bar方法是否包含catchError操作符,若有则错误会被拦截,无法传递到组件的订阅回调。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 13:55:17