了解Angular的fakeBackendProvider,MockBackEnd和MockConnection

时间:2017-11-03 07:07:29

标签: angular angular-test

我正在尝试在测试我的Angular应用时模拟一些http请求。我通过使用Angular的MockBackEnd和MockConnection在互联网上关注使用fakeBackendProvider的流行示例。虽然我很了解代码,但我想更详细地了解这些提供商的内部工作。

他们如何拦截http请求?例如,当我的代码调用http.get()时,他们会联系到什么,谁替换了什么,以及如何?

任何参考资料都非常有用。

2 个答案:

答案 0 :(得分:2)

尝试使用角度为4.3.X的新增的HttpClient。它提供了实现HttpInterceptor的简便方法。 拦截,

使用具有Intercept方法的HttpInterceptor接口,您必须在类中覆盖它。 下面给出的示例代码,

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);
    }
}

我认为你也在努力编写单元测试,为了做到这一点

Angular 4提供了两个很棒的类来使用HttpTestingController,HttpClientTestingModule。在使用之前,请确保在module.ts文件中提供HttpClientModule。

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);
    });
  });
});

答案 1 :(得分:1)

对于mockbackend,你可以做这样的事情,

  1. 在您的应用程序中包含正确的提供程序,如下所示,在您的情况下,它将是Http。 ......提供者:[Http,...]

  2. 如果您注意到我们使用了ReflectiveInjector类和方法resolveAndCreate,那么您的测试文件将包含以下代码或配置。此方法将帮助您创建具有所有依赖项的必需类的对象。 ex this.yourService = this.injector.get(YourService);

  3. 以下两行将帮助您的测试代码与虚假后端连接

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

    提供和useClass,现在无论何时创建ConnectionBackend类对象,它都将与MockBackend类对象一起映射,

    现在每个示例的测试用例(&#39; getNames()都应返回一些名称&#39;,可以使用this.lastConnection将用于连接你的mockedbackend,你必须创建一个使用下面的代码片段中的Response和ResponseOptions类进行响应。

     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');
         }));
    });