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

Angular Jasmine单元测试报错:.subscribe is not a function问题求助

Angular单元测试:解决getMakePaymentState$.subscribe is not a function报错

问题根源

你遇到的报错是因为**mockMakePaymentState对象中没有定义getMakePaymentState$方法**,直接用spyOn监听一个不存在的方法时,Jasmine无法正确创建该方法的间谍,导致组件调用this._payStateService.getMakePaymentState$()时,这个方法实际不存在,自然无法调用.subscribe()。

另外你的测试代码里还监听了getBankPayments,但这个方法同样没在mock对象里定义,后续也会触发类似问题,需要一起处理。

解决方案

步骤1:在Mock对象中预定义所有需要监听的方法

在mockMakePaymentState中添加getMakePaymentState$和getBankPayments的空实现,返回合法的Observable(因为组件会订阅这些方法的返回值):

let mockMakePaymentState = {
  getPaymentDetails$: () => of({} as IPaymentDetails),    
  getDetails: () => {},
  getUserInfo: () => {},
  getMakePaymentState$: () => of({} as IPaymentDetails), // 新增方法,返回空Observable
  getBankPayments: () => of({} as PaymentBankDetails) // 新增方法,返回空Observable
};

步骤2:修改测试用例中的间谍逻辑

现在可以正常用spyOn覆盖这些预定义方法的返回值:

it('should call ngOnInit', () => {
  spyOn(mockMakePaymentState, 'getDetails').and.returnValue(of(paymentInfoDetails));
  spyOn(mockMakePaymentState, 'getBankPayments').and.returnValue(of(paymentBankDetails));
  spyOn(mockMakePaymentState, 'getMakePaymentState$').and.returnValue(of(makePaymentState));

  fixture.detectChanges();
});

注:and.returnValue(of(...))比callFake更简洁,适合直接返回Observable的场景。

修改后的完整测试代码

fdescribe('DetailsComponent', () => {
  let component: DetailsComponent;
  let fixture: ComponentFixture<DetailsComponent>;
  let httpMock: HttpTestingController;  
  let formModule: FormsModule;

  let form = new FormGroup({
    username: new FormControl('', Validators.required),
    dob: new FormControl('')
  });

  let mockbillingService = {
    getDetails: () => {},
    getBankDetails: () => {}
  }

  
  let mockMakePaymentState = {
    getPaymentDetails$: () => of({} as IPaymentDetails),    
    getDetails: () => {},
    getUserInfo: () => {},
    getMakePaymentState$: () => of({} as IPaymentDetails), // 新增
    getBankPayments: () => of({} as PaymentBankDetails) // 新增
  };

   class MatDialogMock {
    open() {
      return {
        afterClosed: () => of({action: true})
      };
    }
  }

  let paymentInfoDetails = <PaymentInfoDetails>{};
  let paymentBankDetails = <PaymentBankDetails>{};
  let makePaymentState = <IPaymentDetails> {}
  
  paymentInfoDetails.banks = [paymentBankDetails];
  
  beforeEach(async () => {     
    await TestBed.configureTestingModule({
      declarations: [ ],
      imports: [ FormsModule, ReactiveFormsModule],
      providers: [
        { provide: BillingService, useValue: mockbillingService },
        {provide: PayState, useValue: mockMakePaymentState},
        { provide: MatDialog, useClass: MatDialogMock } 
      ]
    })
    .compileComponents();

    fixture = TestBed.createComponent(DetailsComponent);
    component = fixture.componentInstance;
    httpMock = TestBed.inject(HttpTestingController);
    formModule = TestBed.inject(FormsModule);
  });


  it('should call ngOnInit', () => {
    spyOn(mockMakePaymentState, 'getDetails').and.returnValue(of(paymentInfoDetails));
    spyOn(mockMakePaymentState, 'getBankPayments').and.returnValue(of(paymentBankDetails));
    spyOn(mockMakePaymentState, 'getMakePaymentState$').and.returnValue(of(makePaymentState));

    fixture.detectChanges();
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 06:12:48