Understanding Angular's fakeBackendProvider, MockBackEnd and MockConnection

人走茶凉 提交于 2019-12-24 21:11:59

问题


I am trying to mock some http requests while testing my Angular app. I am following popular examples over the internet that uses fakeBackendProvider by utilizing Angular's MockBackEnd and MockConnection. Though I understand the code well I would like to understand more in-detail the internal working of these providers.

How do they intercept http requests? For instance when my code make calls to http.get() who gets hooked to what, who replaces what, and how?

Any reference material would be highly helpful.


回答1:


Try HttpClient which is new from angular 4.3.X. It provides easy way to implement the HttpInterceptor. To intercept,

Use HttpInterceptor interface that has a method Intercept which you will have to override in your class. a sample code as given below,

import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent, HttpResponse, HttpErrorResponse } from '@angular/common/http';
import { Observable } from 'rxjs/Observable';

import 'rxjs/add/Observable/throw';
import 'rxjs/add/operator/catch';
import 'rxjs/add/Observable/of';
import 'rxjs/add/operator/do';

export class YourInterceptor implements HttpInterceptor{

    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{
// Your interceptor code comes here.
// you wish to change the request, change here.
    request = request.clone({
      setHeaders: {
        Authorization: `Bearer ${this.auth.getToken()}`
      }
    });
               return next.handle(request);
    }
}

I think you are trying to write unit testing also for the same, in order to do so

Angular 4 provides two awesome classes to work with HttpTestingController, HttpClientTestingModule. Make sure you provide HttpClientModule in the module.ts file before using this.

import { TestBed, inject, getTestBed } from '@angular/core/testing';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { HttpTestingController, HttpClientTestingModule } from '@angular/common/http/testing';

import { YourService } from './get-name-service.service';

describe('YourService', () => {

  let injector: TestBed;
  let httpMock: HttpTestingController;   
  let yourService: YourService;

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports:[HttpClientTestingModule],
      providers: [YourService]
    });

    injector = getTestBed();
    httpMock = injector.get(HttpTestingController);
    yourService = TestBed.get(YourService);

  });

  describe('#getUsers', () => {
    it('should return an Observable<User[]>', () => {
      const dummyUsers = [
        { login: 'John' },
        { login: 'Doe' }
      ];

    yourService.getNames().subscribe(users => {
       console.log('I am here in yourService method');
        expect(users.length).toBe(2);
        expect(users).toEqual(dummyUsers);
      });

    const req = httpMock.expectOne('http://localhost:8080/dev/getNames');
      expect(req.request.method).toBe("GET");
      req.flush(dummyUsers);
    });
  });
});



回答2:


For mockbackend, you can do something like this,

  1. Include correct provider in your application as given below, in your case it will be Http. ...Provider:[Http, ...]

  2. Your test file will house following codes or configuration, in this if you notice we have used ReflectiveInjector class and a method resolveAndCreate. This method will help you create an object of a required class with all its dependencies. ex this.yourService = this.injector.get(YourService);

following two lines will help your test code to connect with the fake backend

          {provide: ConnectionBackend, useClass: MockBackend},
          {provide: RequestOptions, useClass: BaseRequestOptions},

provide and useClass, now whenever your ConnectionBackend class object is created it would be mapped with MockBackend class object,

Now each of the test case for an example it('getNames() should return some names', can use this.lastConnection will be utilized to connect with your mockedbackend, there you will have to create a Response by using Response and ResponseOptions class as given below in the code snippet below.

 describe('MockBackend NameService Example', () => {
      beforeEach(() => {
        this.injector = ReflectiveInjector.resolveAndCreate([
          {provide: ConnectionBackend, useClass: MockBackend},
          {provide: RequestOptions, useClass: BaseRequestOptions},
          Http,
          YourService,
        ]);
        this.yourService = this.injector.get(YourService);
        this.backend = this.injector.get(ConnectionBackend) as MockBackend;
        this.backend.connections.subscribe((connection: any) => this.lastConnection = connection);
      });
  it('getNames() should return some names', fakeAsync(() => {
       let result: String[];
       this.yourService.getNames().then((names: String[]) => result = names);
       this.lastConnection.mockRespond(new Response(new ResponseOptions({
         body: JSON.stringify({data: ["Deepak Test1", "Deepak Test2"]}),
       })));
       tick();       
       expect(result.length).toEqual(2, 'should contain given amount of Names');
       expect(result[0]).toEqual("Deepak Test1", ' NAME_ONE should be the first Name');
       expect(result[1]).toEqual("Deepak Test2", ' NAME_TWO should be the second Name');
     }));
});


来源:https://stackoverflow.com/questions/47090244/understanding-angulars-fakebackendprovider-mockbackend-and-mockconnection

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!