首页 > 解决方案 > Angular 测试模拟 Http 服务

问题描述

我正在为 Angular 应用程序编写单元测试。我想模拟来自 http 调用服务的值。

组件.spec.ts

let apiService: ApiService;
let mockedHttpClient: HttpClient = mock(HttpClient);

beforeEach(async () => {
  await TestBed.configureTestingModule({
    declarations: [EditorComponent],
    providers: [
      { provide: ApiService, useValue: apiService },
      {
        provide: HttpClient,
        useFactory: () => instance(mockedHttpClient),
      },
    ],
    imports: [HttpClientModule],
  }).compileComponents();
});

beforeEach(() => {
  apiService = TestBed.inject(ApiService);

  fixture = TestBed.createComponent(EditorComponent);
  component = fixture.componentInstance;

  fixture.detectChanges();
});

it("should get Informations", (done: DoneFn) => {
  component.id = "id1";
  spyOn(apiService, "getInfosById").and.returnValue(of(infos));

  component.getInformations();

  expect(component.infos).toEqual(infos);
});

组件.ts

private readonly unsubscribe = new Subject();

getInformations() {
   this.apiService
      .getInfos(this.id)
      .pipe(takeUntil(this.unsubscribe))
      .subscribe((data) => {
        this.infos = data;
   })
}

ngOnDestroy() {
    this.unsubscribe.next();
    this.unsubscribe.complete();
  }

api-service.ts

public getInfos(id: string) {
    return this.http.get<Infos>(
              this.apiUrl +'infos/' + id,
              httpOptions)}

我想模拟上面的功能。

错误

<spyOn> : could not find an object to spy upon for getInformations()

我究竟做错了什么?有没有更好的方法来模拟带有 .pipe 和 .subscribe 的 http-Service?

标签: angulartypescriptunit-testingkarma-jasmine

解决方案


为了模拟 HTTP 调用的响应,我会做这样的事情:

@Injectable()
class MockApiService extends ApiService {
  getInfos(): any {
     const data = {} // Fill the object as per how the response comes
     return data;
  }
}

beforeEach(async () => {
        await TestBed.configureTestingModule({
          declarations: [EditorComponent],
          providers: [
             <!------- You need to add the below line -----!>
            { provide: ApiService, useClass: MockApiService },
            {
              provide: HttpClient,
              useFactory: () => instance(mockedHttpClient),
    
            },    
          ],
          imports: [
            HttpClientModule
          ]
        })
          .compileComponents();
      });

it('should run #getInformations() method in component', () => {
  spyOn(component, 'getInformations').and.callThrough();
  component.getInformations();
  expect(component.getInformations).toHaveBeenCalled();
});

// THe above test case will cover the success scenario of the service call

推荐阅读