Angular模拟多个HTTP调用

时间:2018-06-03 11:22:33

标签: angular typescript rxjs karma-jasmine angular-httpclient

我有一个服务正在返回多个http调用的forkjoin。我想测试这个场景。

    class CommentService{
     addComments(){

let ob1 = Observable.of({});
    let ob2 = Observable.of({});
if(any condition)
        ob1 = {this.http.post('/url/1')};
if(any condition)
            ob2 = {this.http.post('/url/2'};
        return Observable.forkJoin(ob1,ob2)
           }
     }

以上是我的服务类。我怎么能模拟http调用。

describe("CommentService", () => {
  let httpClient: HttpClient;
  let httpTestingController: HttpTestingController;
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpClientModule, HttpClientTestingModule],
      providers: [CommentService]
    });

    httpClient = TestBed.get(HttpClient);
    httpTestingController = TestBed.get(HttpTestingController);
  });

  it('addComments() call with normal and gate', inject([CommentService], (service: CommentService) => {


    let cmts = service.addComments();

    const reqGateComment = httpTestingController.expectOne('/url/1');
    expect(reqGateComment.request.method).toEqual('POST');

    const reqFactComment = httpTestingController.expectOne('/url/2');
    expect(reqFactComment.request.method).toEqual('POST');

    reqGateComment.flush({});
    reqFactComment.flush({});


    httpTestingController.verify();

    cmts.subscribe(results=>{
       expect(results.length).toEqual(2);
    });

  }));


});

我得到以下测试失败。 CommentService addFactsAndComments()调用normal和gate

错误:符合条件的匹配请求“匹配网址:

 '/url/1", found none.

4 个答案:

答案 0 :(得分:1)

我遇到了类似的问题,我使用 fakeAsync 解决了它。

it('addComments() call with normal and gate', fakeAsync( inject([CommentService], (service: CommentService) => {

    service.addComments().subscribe(results=>{
        expect(results.length).toEqual(2);
     });

    const reqGateComment = httpTestingController.expectOne('/url/1');
    expect(reqGateComment.request.method).toEqual('POST');
    reqGateComment.flush({});

    tick(10000);

    const reqFactComment = httpTestingController.expectOne('/url/2');
    expect(reqFactComment.request.method).toEqual('POST');
    reqFactComment.flush({});


    httpTestingController.verify();

  })));

答案 1 :(得分:0)

这是因为您使用HttpClient方法将of创建的可观察对象包装在新的joined$ = forkJoin(obs$(post1$),obs$(post2$)) 中。

通过

obs$

注意:$代表可观察的

您创建了一个新的observable:

  • 订阅外部obs$
  • 等待他们完成,
  • 收集他们上次发出的值(在本例中为post1 $和post2 $)
  • 按照源流的顺序将收集的值作为数组返回

因为我们只订阅了外部addComments(){ const ob1 = this.http.post('/url/1'); const ob2 = this.http.post('/url/2'); return Observable.forkJoin(ob1,ob2); } ,所以您的测试失败了

  

'/ url / 1“,找不到。

因为我们从未订阅内部帖子$,这意味着请求未被发送。

将您的服务方式更改为:

TCPDF

答案 2 :(得分:0)

我最近遇到了同样的问题,这就是我解决的方法。 首先,我不得不忘记HttpTestingController和HttpClientTestingModule并编写自己的模拟实现类。以下是我在Message控制器中测试多个请求的解决方案,该控制器使用forkJoin处理多个请求(MessageService中的getPosts,getComments)。

class MockMessageService {
    getPosts() {
        return of([{ id: 1, title: "Post 1", body: "Post Content 1" }, { id: 2, title: "Post 2", body: "Post Content 2" }]);
    }

    getComments() {
                return of([{ id: 1, postId:1, name: "quo vero", body: "est natus enim nihil est" }, { id: 2, postId:2, name: "id labore", body: "quia molestiae reprehenderit" }]);
    }
}

describe('MessageComponent', () => {
    let component: MessageComponent;   
    let service: MessageService; 
    let el: DebugElement;

    beforeEach(() => {
        TestBed.configureTestingModule({
            declarations: [
                MessageComponent              
            ],
            providers: [{ provide: MessageService, useClass: MockMessageService }]            
        });

        fixture = TestBed.createComponent(MessageComponent);
        component = fixture.componentInstance;
        el = fixture.debugElement;
        service = el.injector.get(MessageService);

    });

it('should get message posts and comments on Oninit', () => {

        spyOn(service, 'getPosts').and.callThrough();
        spyOn(service, 'getComments').and.callThrough();

        component.ngOnInit();

        expect(service.getPosts).toHaveBeenCalled();
        expect(service.getComments).toHaveBeenCalled();

    });

});

答案 3 :(得分:0)

在调用 addComments 之前,您需要调用 expectOne 并订阅返回的 observable。只有在订阅时才会触发 httpClient 请求

这是导致测试失败的核心问题

顺便说一句,您不使用 fakeAsync 是对的,因为使用 HttpClientTestingModule 是同步的