【问题标题】:rxjs mock response into a pipe/taprxjs 模拟响应到管道/水龙头
【发布时间】:2026-01-13 22:40:02
【问题描述】:

我正在为 Angular 7.1 应用程序进行单元测试。我们使用 rxjs 6.3.3。我的组件有一个看起来像这样的服务调用。

this.registrationservice
            .createAccount(model)
            .pipe(
                tap(
                    (resp: {}) => {
                        this.router.navigate([url]);
                    },
                    (error: any) => {
                        this.isError = true;
                        this.registrationState.resetData();
                        this.resetUrl = this.registrationState.verifyStepState(RegistrationStepName.confirm);
                    }
                ),
                finalize(() => {
                    this.isLoading = false;
                })
            )
            .subscribe();

当我尝试返回错误响应时,它永远不会进入 .tap 错误处理程序?我该如何模拟呢?这是我的测试

it("Register User error", fakeAsync(() => {
        let errorResponse = {
            statusCode: "400",
            error: "no good"
        };
        userRegisterSvcStub.createAccount.and.throwError(ErrorObservable.create(errorResponse));
        let model = new UserRegisterModel({ userregistrationtypeid: modelProviderType.id, ...modelNpi, ...modelCreateAccount });
        registerDataStateSpy.getRegisterUserData.and.returnValue(model);
        registerDataStateSpy.verifyStepState.and.returnValue("../beginning");
        component.ngOnInit();
        tick();
        expect(mockRouter.navigate).not.toHaveBeenCalled();
        expect(component.resetUrl).toEqual("../beginning");
    }));

【问题讨论】:

    标签: javascript angular unit-testing rxjs karma-jasmine


    【解决方案1】:

    为克里斯蒂安的回答提供更多细节......

    从您使用它的方式来看,我假设userRegisterSvcStub 是一个间谍对象,而createAccount() 是该对象的一个​​间谍方法?如果是这样,那么您当前在这里使用的代码:

    userRegisterSvcStub.createAccount.and.throwError(ErrorObservable.create(errorResponse));
    

    使用 jasmine throwError() 方法实际上会引发错误,如文档中的 here 所述。

    我认为您想要的是按照 Christian 的建议使用 rxjs throwError。为此,您的代码将如下所示:

    import { throwError } from 'rxjs'; // up with your other imports
    
    userRegisterSvcStub.createAccount.and.returnValue(throwError(errorResponse));
    

    我希望这会有所帮助。

    【讨论】:

    • 谢谢,但不幸的是它仍然进入水龙头中的“成功”块......试图弄清楚我可以给模拟什么让它认识到这是一个错误而不是成功
    • 我的错……这行得通!……我的其他间谍电话之一仍然模拟了以前的数据,因此它没有到达我的代码……需要更多咖啡……干杯!
    【解决方案2】:

    您可以使用 rxjs 中的 throwError 运算符创建一个 Observable,它会立即抛出您传递给函数的任何内容。

    【讨论】: