Rxjs5 测试 Angular 2

Rxjs5 Testing With Angular 2

我有一个 Angular 2 服务连接到 Angular Http 服务,使用 Rxjs 5 连接到 restful 网络服务。 getObjects 以有意义对象的 Observable 数组的形式简单地调用 returns 已解析的 Json。我一直在尝试让可观察的 returned 来解决我模拟的 Http 响应,但我还没有真正找到一个有效的答案。

测试代码:

import { getTestBed } from '@angular/core/testing';
import { MockBackend } from '@angular/http/testing';
import { TestScheduler } from "rxjs";

import { expect } from 'chai';
import { spy } from 'sinon';
import TestingUtilities from "../shared/test.utilities";

import Service from './service';
import ReturnObject from "../returnobject";

describe(`ServiceTests`, () => {
  let MOCK_DATA: string = ...mocked JSON string response...;

  let service: Service
  let backend: MockBackend
  let scheduler: TestScheduler

  function assertDeepEqualFrame(actual:any, expected:any) {
    console.log("test");
    if (!expected === actual) {
      throw new Error('Frames not equal!');
    }
  }

  beforeEach(() => {
    TestingUtilities.configureTestingModuleForMockHttp(getTestBed(), function () {
      return Service
    });

    backend = getTestBed().get(MockBackend);
    service = getTestBed().get(EarthquakeService);
    scheduler = new TestScheduler(assertDeepEqualFrame);
  });

  it('should return mocked data', () => {
    TestingUtilities.mockHttpResponse(backend, MOCK_DATA);

    let observables = service.getObjects();
    scheduler.expectObservable(observables).toBe("", functionToCreateMockObjects());
  });

TestingUtilities 只是围绕模拟 https://semaphoreci.com/community/tutorials/testing-angular-2-http-services-with-jasmine 提供的 Angular 提供的 Http 服务的解决方案的便利包装。上面的代码可以编译,但它实际上似乎没有 return 模拟的 Observables 也没有断言任何东西。我正在努力了解应该如何使用 TestScheduler 来调用现有服务并获取可观察数据以进行验证。有人有什么想法吗?

我不使用 TestScheduler 来测试可观察对象。但我真的很喜欢我使用的以下方法:

import {TestBed, inject} from '@angular/core/testing';
import {BaseRequestOptions, Http, HttpModule, ResponseOptions, Response} from '@angular/http';
import {MockBackend} from '@angular/http/testing';
import {Book} from '../custom-types/book';
import {GoogleBooksService, API_PATH_SINGLE_BOOK} from './google-books.service';

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

describe('Service: GoogleBooks', () => {
    beforeEach(() => {
        TestBed.configureTestingModule({
            imports: [HttpModule],
            providers: [
                GoogleBooksService,
                BaseRequestOptions,
                MockBackend,
                mockedHttpProvider
            ],
        });
    });

    it('should call the google books api',
        inject([GoogleBooksService, MockBackend], (service: GoogleBooksService, backend: MockBackend) => {
            let queryId: string = "someId";
            let expectedResponse: Book = {
                description: 'It's just Angular',
                title: 'How to test Observables'
            };

            backend.connections.subscribe(connection => {
                expect(connection.request.url).toBe(API_PATH_SINGLE_BOOK + queryId);
                let response = new ResponseOptions({body: JSON.stringify(expectedResponse)});
                connection.mockRespond(new Response(response));
            });

            service.getBookByGoogleBookId(queryId).subscribe(response => {
                expect(response).toEqual(expectedResponse);
            })
        })
    );
});

服务实施:

@Injectable()
export class GoogleBooksService {

    constructor(private http: Http) {
    }

    getBookByGoogleBookId(id: string): Observable<Book> {
        return this.http.get(API_PATH + id)
            .map(res => res.json());
    }
}

尝试使用模拟后端以这种方式测试您的服务:

describe(`ServiceTests`, () => {
  let MOCK_DATA: string = ...mocked JSON string response...;

  let earthquakeService: EarthquakeService;

  beforeEach(() => {
    TestBed.configureTestingModule( {
        providers: [
            EarthquakeService,
            { provide: XHRBackend, useClass: MockBackend },
            { provide: ComponentFixtureAutoDetect, useValue: true }
        ],
        imports: [
            HttpModule
        ]
    } )
    .compileComponents();
    });
  });

  it('should return mocked data', async( inject( [ Http, XHRBackend ], ( http: Http, backend: MockBackend ) => {
    backend.connections.subscribe( ( c: MockConnection ) => c.mockRespond( response ) );

    let options = new ResponseOptions( { status: 200, body: { data: MOCK_DATA } } );
    response = new Response( options );

    earthquakeService = new EarthquakeService( http );

    earthquakeService.getObjects().subscribe( results => {
        expect( results ).toEqual( { data: MOCK_DATA } );
    } ););

这会单独测试您的服务。可以通过扩展此框架或在这些测试中创建存根服务来测试使用此服务的其他组件。