Подтвердить что ты не робот

Тестирование Angular2 службы с макетным бэкэнд

Во-первых: я знаю, что Angular2 находится в альфе и часто меняется.

Я работаю с Angular2. Существует инъекционная служба с зависимостью HTTP, которую я бы хотел протестировать, используя макетную копию. Служба работает, когда приложение запускается, но мне не повезло, написав тест и получив ответный макет. Любое понимание, есть ли что-то очевидное в тестовой установке или реализации, которую я пропускаю?

Услуги/core.ts:

import { Injectable } from 'angular2/angular2';
import { Http } from 'angular2/http';

@Injectable()
export class CoreService {

    constructor(public http:Http) {}

    getStatus() {
        return this.http.get('/api/status')
            .toRx()
            .map(res => res.json());
    }
}

Услуги/core_spec.ts:

import {
    AsyncTestCompleter,
    TestComponentBuilder,
    By,
    beforeEach,
    ddescribe,
    describe,
    el,
    expect,
    iit,
    inject,
    it,
    xit
} from 'angular2/test';
import { MockBackend, MockConnection, BaseRequestOptions, Http, Response } from 'angular2/http';
import { Injector, bind } from 'angular2/angular2';
import { ObservableWrapper } from 'angular2/src/core/facade/async'

import { CoreService } from 'public/services/core'

export function main() {

    describe('public/services/core', () => {

        let backend: MockBackend;
        let response: Response;
        let coreService: CoreService;
        let injector: Injector;

        afterEach(() => backend.verifyNoPendingRequests());

        it('should get status', inject([AsyncTestCompleter], (async) => {

            injector = Injector.resolveAndCreate([
                BaseRequestOptions,
                MockBackend,
                bind(Http).toFactory((backend, options) => {
                    return new Http(backend, options)
                }, [MockBackend, BaseRequestOptions]),
                bind(CoreService).toFactory((http) => {
                    return new CoreService(http);
                }, [Http])
            ]);

            backend = injector.get(MockBackend);
            coreService = injector.get(CoreService);
            response = new Response('foo');

            ObservableWrapper.subscribe<MockConnection>(backend.connections, c => {
                expect(c.request.url).toBe('/api/status');
                c.mockRespond(response);
            });

            // attempt #1: fails because res argument is undefined
            coreService.getStatus().subscribe(res => {
                expect(res).toBe('');
                async.done();
            });

            // attempt #2: fails because emitter.observer is not a function
            ObservableWrapper.subscribe(coreService.getStatus(), res => {
                expect(res).toBe('');
                async.done();
            });

        }));
    });

}

по теме: https://github.com/angular/angular/issues/3502 https://github.com/angular/angular/issues/3530

4b9b3361

Ответ 1

Я только что нашел эту тему, ища советы по тестированию, но я не вижу прямого ответа на этот вопрос...

Этот файл основан на Angular RC.1

Служба тестирования с помощью Mock Backend

Скажем, ваша служба:

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';

@Injectable()
export class CoreService {
  constructor(private http: Http) {}

  getStatus() {
    return this.http.get('/api/status');
  }
}

Тест на вышеприведенную службу будет выглядеть следующим образом:

import {
  beforeEach,
  beforeEachProviders,
  describe,
  expect,
  inject,
  it,
} from '@angular/core/testing';

import { provide } from '@angular/core';
import { BaseRequestOptions, Response, ResponseOptions } from '@angular/http';
import { MockBackend, MockConnection } from '@angular/http/testing';

describe('Http', () => {

  beforeEachProviders(() => [
    CoreService,
    BaseRequestOptions,
    MockBackend,
    provide(Http, {
      useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
        return new Http(backend, defaultOptions);
      },
      deps: [MockBackend, BaseRequestOptions]
    })
  ]);

  beforeEach(inject([MockBackend], (backend: MockBackend) => {
    const baseResponse = new Response(new ResponseOptions({ body: 'status' }));
    backend.connections.subscribe((c: MockConnection) => c.mockRespond(baseResponse));
  }));

  it('should return response when subscribed to getStatus',
    inject([CoreService], (coreService: CoreService) => {
      coreService.getStatus().subscribe((res: Response) => {
        expect(res.text()).toBe('status');
      });
    })
  );

})

То, что вам действительно нужно посмотреть, должно быть правильно издевается над beforeEachProviders. Сам тест довольно прост и заканчивается подпиской на сервисный метод.


Примечание. Не забудьте сначала установить базовые провайдеры:

import { setBaseTestProviders } from '@angular/core/testing';
import {
  TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS,
  TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS,
} from '@angular/platform-browser-dynamic/testing';

setBaseTestProviders(TEST_BROWSER_DYNAMIC_PLATFORM_PROVIDERS, TEST_BROWSER_DYNAMIC_APPLICATION_PROVIDERS);

Ответ 2

С тех пор, как мы задали этот вопрос, мы обновили до Angular2 RC 1. Наш импорт выглядит как Wojciech Kwiatek (спасибо за ваш ответ!), но наша стратегия тестирования немного отличается. Мы хотели заявить по запросу, а также ответ. Вместо использования beforeEachProviders() мы использовали beforeEach(), где мы создали наш собственный инжектор и сохранили ссылку на проверку обслуживания и ложный бэкэнд. Это позволяет нам утверждать запрос и управлять ответом внутри теста, и это позволяет нам использовать метод verifyNoPendingRequests() после каждого теста.

describe('core-service', () => {

  let service: CoreService;
  let backend: MockBackend;

  beforeEach(() => {
    injector = ReflectiveInjector.resolveAndCreate(<any> [
        CoreService,
        BaseRequestOptions,
        MockBackend,
        provide(Http, {
            useFactory: (mockBackend, defaultOptions) => new Http(mockBackend, defaultOptions),
            deps: [MockBackend, BaseRequestOptions]
        })
    ]);

    service = <CoreService> injector.get(CoreService);
    backend = <MockBackend> injector.get(MockBackend);
  });

  afterEach(() => backend.verifyNoPendingRequests());

  it('should get status', () => {

    backend.connections.subscribe((c: MockConnection) => {
      expect(c.request.url).toEqual('api/status');
      c.mockRespond(new Response(new ResponseOptions({ body: 'all is well' })));
    });

    service.getStatus().subscribe((status) => {
      expect(status).toEqual('all is well');
    });

  }));
});

Изменить: Plunker обновлен до RC2. https://plnkr.co/edit/nlvUZVhKEr8d2mz8KQah?p=preview