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

Mock Axios请求失败场景下,Angular组件测试未触发错误回调

问题排查与解决:Jasmine测试未触发错误分支

问题场景

封装Axios请求的UserUtils类中,updateUserData方法在请求失败时返回rxjs的throwError;UserComponent调用该方法后,期望成功时触发showSuccessModal,失败时触发showErrorModal。但Jasmine测试Mock该方法返回Promise.reject时,始终执行成功分支,报错Error: Expected spy showErrorModal to have been called。

核心问题分析

  1. Promise链错误处理失效:UserUtils的catch块返回了rxjs的Observable(throwError),而非Promise.reject。Promise的catch若返回非Promise类型的值(包括Observable),会被当作成功结果传递给下一个then的成功分支,导致组件永远走成功逻辑。
  2. 组件错误回调参数错误:组件中错误回调的参数名是err,但调用showErrorModal时传的是error,就算触发错误分支也会传递undefined。
  3. 测试异步逻辑未等待:测试用例同步执行,未等待update方法中的Promise异步操作完成就执行断言,此时回调还未触发。

修复步骤

1. 修正UserUtils的错误返回值

将catch块中的throwError替换为Promise.reject,维持Promise链的错误传递:

// utils.ts 修改后
import axios, { AxiosResponse } from 'axios';

axios.defaults.withCredentials = true;
axios.defaults.responseType = 'json';

export class UserUtils {
    public updateUserData(data) {
        return axios.post('http://mock.rest.server.com:1234/rest/update/user/', data, 
            {
                withCredentials: true,
                responseType: 'json' as 'json'
            })
            .then(resp => resp)
            .catch(error => {
                // 用Promise.reject替代throwError,保持Promise错误链
                return Promise.reject('error updating user data');
            });
    }
}

2. 修正UserComponent的参数错误

将错误回调中传递的参数从error改为err,与回调参数名一致:

// userComponent.ts 修改后
import { UserUtils } from './utils'; // 修复import放在类内部的语法错误

export class UserComponent {
    public userUtils: UserUtils = new UserUtils();

    // 按钮点击方法
    public update(content) {
        this.userUtils.updateUserData(content)
           .then((data) => {
               this.showSuccessModal();
           }, (err) => {
               // 参数名与回调一致,避免传递undefined
               this.showErrorModal(err);
           });
    }

    // 补充方法定义(测试依赖)
    showSuccessModal(): void {}
    showErrorModal(error: any): void {}
}

3. 修正Jasmine测试的异步处理

使用async/await等待Promise异步操作完成后再执行断言:

// userComponent.spec.ts 修改后
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { UserComponent } from '../../../user/userComponent';
import { UserUtils } from '../../../user/utils';

describe('User Comp test', () => {
    beforeAll(async () => {
        await TestBed.configureTestingModule({
            declarations: [UserComponent]
        }).compileComponents();
    });

    describe('User Comp (with beforeEach)', () => {
        let component: UserComponent;
        let fixture: ComponentFixture<UserComponent>;

        beforeEach(async () => {
            fixture = TestBed.createComponent(UserComponent);
            component = fixture.componentInstance;
            fixture.detectChanges();
        });

        it('should show error modal', async () => {
            const errorModalSpy = spyOn(component, 'showErrorModal');
            // Mock updateUserData返回失败的Promise
            spyOn(component.userUtils, 'updateUserData').and.returnValue(Promise.reject('error updating'));

            // 等待异步操作完成
            await component.update({test: 'test'});
            
            // 断言错误方法被调用,且参数正确
            expect(errorModalSpy).toHaveBeenCalledWith('error updating');
        });
    });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 14:15:33