【问题标题】:Understanding Angular's fakeBackendProvider, MockBackEnd and MockConnection了解 Angular 的 fakeBackendProvider、MockBackEnd 和 MockConnection
【发布时间】:2017-11-03 07:07:29
【问题描述】:

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

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

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

【问题讨论】:

    标签: angular angular-test


    【解决方案1】:

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

    【讨论】:

    • 我知道有HttpClient。感谢您的投入。但是,由于我已经在学习使用 Http 的教程,因此我想通过使用 Angular 的 MockBackEnd 和 MockConnection 来了解 akeBackendProvider 的内部工作原理。对此方向的任何帮助将不胜感激。
    • 我同意,使用 HttpClient,即使您正在学习教程,但它已过时且已弃用。
    【解决方案2】:

    对于 mockbackend,你可以这样做,

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

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

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

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

    provide and useClass,现在无论何时创建 ConnectionBackend 类对象,它都会映射到 MockBackend 类对象,

    现在每个测试用例的例子 it('getNames() 应该返回一些名称',可以使用 this.lastConnection 来连接你的 mockedbackend,你必须使用 Response 创建一个 Response 和ResponseOptions 类在下面的代码 sn-p 中给出。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-01-19
      • 1970-01-01
      • 1970-01-01
      • 2017-06-28
      • 2017-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多