0

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

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

任何参考资料都会非常有帮助。

4

2 回答 2

3

尝试 HttpClient,它是 Angular 4.3.X 的新功能。它提供了实现 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);
    });
  });
});
于 2017-11-03T07:28:05.157 回答
1

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

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

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

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

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

提供和使用类,现在无论何时创建 ConnectionBackend 类对象,它都会与 MockBackend 类对象映射,

现在每个示例的测试用例它('getNames()应该返回一些名称',可以使用 this.lastConnection 将用于连接您的模拟后端,您必须使用 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');
     }));
});
于 2017-11-07T06:56:21.127 回答