0

我有一个 debService,它通过简单的 HttpClient 请求调用后端 API。它返回一个可观察的。现在,在 AppComponent 中,我正在调用 debService 的方法来获取债务。我想确保,当债务被提取时,名为 logGetDebtAttempt 的方法也被调用。

import { Component } from '@angular/core';
import { Observable, Subject, Subscriber, TeardownLogic } from 'rxjs';
import { DebtService } from './services/debt.service';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private debtService: DebtService) {
  }

  async getDebt() {
    // getNationalDebt() returns Observable<Number>
    await this.debtService.getNationalDebt().toPromise();
    this.logGetDebtAttempt();
  }

  logGetDebtAttempt() {
  }
}

这就是为什么我写了这样的测试:

import { ComponentFixture, TestBed } from '@angular/core/testing';
import { RouterTestingModule } from '@angular/router/testing';
import { cold } from 'jasmine-marbles';
import { Observable, Subscriber, TeardownLogic } from 'rxjs';
import { AppComponent } from './app.component';
import { DebtService } from './services/debt.service';
import { HttpClientTestingModule } from '@angular/common/http/testing'


const chartServiceStub = {
  getNationalDebt(): Observable<Number> {
    return cold('--x|', { x: 1 });
  }
};

describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        HttpClientTestingModule
      ],
      declarations: [
        AppComponent
      ],
      providers: [
        { provide: DebtService, useValue: chartServiceStub },
        
      ]
    }).compileComponents();

  });

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
  });

  it('should test', async () => {
    spyOn(component, 'getDebt').and.callThrough();
    spyOn(component, 'logGetDebtAttempt').and.callThrough();

    await component.getDebt();

    expect(component.logGetDebtAttempt).toHaveBeenCalled();
  });
});

运行测试时,等待 component.getDebt(); 永远不会结束,它会产生超时。

有人可以解释为什么会这样吗?

4

1 回答 1

0

免责声明:这不会完全回答您的问题。

我认为它的发生是因为--每个破折号是一毫秒的语法。

根据我的经验,由于这些破折号,我从来都不是jasmine-marbles任何大理石测试帮助库的粉丝。

对于您的场景,您甚至不需要弹珠。您可以使用of.

import { of } from 'rxjs';
....
const chartServiceStub = {
  getNationalDebt(): Observable<Number> {
    return of(1);
  }
};

describe('AppComponent', () => {
  let component: AppComponent;
  let fixture: ComponentFixture<AppComponent>;
  beforeEach(async () => {
    await TestBed.configureTestingModule({
      imports: [
        RouterTestingModule,
        HttpClientTestingModule
      ],
      declarations: [
        AppComponent
      ],
      providers: [
        { provide: DebtService, useValue: chartServiceStub },
        
      ]
    }).compileComponents();

  });

  beforeEach(() => {
    fixture = TestBed.createComponent(AppComponent);
    component = fixture.componentInstance;
  });

  it('should test', async () => {
    spyOn(component, 'getDebt').and.callThrough();
    spyOn(component, 'logGetDebtAttempt').and.callThrough();

    await component.getDebt();

    expect(component.logGetDebtAttempt).toHaveBeenCalled();
  });
});

而且,既然它是 a .toPromise,我也会take(1)对它做 a 。我认为有了这个take,它也可能有助于弹珠场景。我知道这很可能是一个 http 调用,并且take不需要,但您可能会争辩说它是更好的设计,因为如果我要使用await,则流不能永远发出。

import { Component } from '@angular/core';
import { Observable, Subject, Subscriber, TeardownLogic } from 'rxjs';
import { DebtService } from './services/debt.service';
import { take } from 'rxjs/operators';
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  constructor(private debtService: DebtService) {
  }

  async getDebt() {
    // getNationalDebt() returns Observable<Number>
    await this.debtService.getNationalDebt().pipe(take(1)).toPromise();
    this.logGetDebtAttempt();
  }

  logGetDebtAttempt() {
  }
}
于 2021-11-02T02:09:13.557 回答