【问题标题】:Test a condition between the request and result of a HTTP request测试 HTTP 请求的请求和结果之间的条件
【发布时间】:2020-01-08 08:31:24
【问题描述】:

假设一个组件方法创建一个 HTTP GET 请求,在等待响应时设置加载状态,并在给出响应时移除加载状态。例如:

getData() {
    this.myService
      .getSomeDate()
      .pipe(tap(_ => {
        this.loading = true;
      }))
      .subscribe(result => {
        this.data = result;
        this.loading = false;
      });
}

您将如何通过测试验证请求和响应之间的状态(例如pipe 部分)是否确实正在加载?我尝试使用HttpTestingController 发送HttpEventType.Sent 事件,但似乎不起作用。调用req.flush() 将导致代码立即转到subscribe 部分,这样也不起作用。这是我用过的测试方法:

it('should have a loading state durin the request', () => {
    component.getData();
    const req = httpClient.expectOne('http://localhost:8080');
    req.event({type: HttpEventType.Sent});

    expect(component.loading).toBe(true);

    req.flush();
    expect(component.loading).toBe(false);
});

【问题讨论】:

    标签: angular testing jasmine


    【解决方案1】:

    备注

    1. 请注意,Observable.pipe 仅在结果值到达时被调用。因此,在getData 方法中,loading 状态应在调用myService.getSomeDateservice 之前设置为true,并且不需要pipe

    2. 在对component 进行单元测试时,您应该模拟相关的服务方法。

    组件

    getData() {
        this.loading = true;
        this.myService.getSomeDate()
          .subscribe(result => {
            this.data = result;
            this.loading = false;
          });
    }
    

    单元测试

    现在您可以尝试在伪异步区域中运行您的测试(使用fakeAsync)并在两个exec 之间使用flush

    import { ComponentFixture, TestBed, fakeAsync, flush} from '@angular/core/testing';
    import { Observable, of } from 'rxjs';
    
    ...
    
    it('should have a loading state durin the request', fakeAsync(() => {
        const myService = TestBed.get(MyService);
        const data = ... // define data to be returned by myService.getSomeDate
        spyOn(myService, 'getSomeDate').and.returnValue(of(data));
    
        component.getData();
    
        expect(component.loading).toBe(true);    
        flush();
        expect(component.loading).toBe(false);
    }));
    

    更新

    of 返回一个Observable,它同步传递作为参数提供的值。因此,上述测试实际上并没有涉及异步代码。这使得flush 无用,正如Andrei Gătej 在下面的评论中提到的那样。通过pipe(delay(1)),我们可以模拟异步处理,现在将使用tick模拟异步时间流逝。

    it('should have a loading state durin the request', fakeAsync(() => {    
        ....
        spyOn(myService, 'getSomeDate').and.returnValue(of(data).pipe(delay(1)));
    
        component.getData();
    
        expect(component.loading).toBe(true);    
        tick(1);
        expect(component.loading).toBe(false);
    }));
    

    【讨论】:

    • 谢谢!那里需要flush 吗?除非of() 使用除queueScheduler 之外的其他调度程序,否则flush 似乎有点多余。还是我错过了什么?
    • @Andrei Gătej:你说得对,of 返回一个Observable,它同步传递作为参数提供的值。所以,这个测试最终没有涉及到异步代码。
    猜你喜欢
    • 2018-03-09
    • 1970-01-01
    • 1970-01-01
    • 2016-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-16
    • 1970-01-01
    相关资源
    最近更新 更多