Tony
Tony

Reputation: 1694

Unittest of angular 2 http get / observable

I am trying to write a unit test that tests that json i get from calling my Api validates against a mock object, but i always ends up with that the data returned from the WebApi is undefined. I believe it is because the Api returns an Observable and that hasn't been resolved when the test run.

Over that last couple of days I have googled everything i can think about related to this, but are completely stuck with no solution in sight. This being my first Angular2 project doesn't help. Anyone here that can point me in the right direction?

This is the Json i get from the WebApi

{
"Categories": [
    "categoryA",
    "categoryB"        
]
}

This is my assert. 'retrivedData' is always undefined no matter what i try

return siteService.getCategories({ category: 'all' }).subscribe((retrivedData) => {
    expect(retrivedData.length).toBe(2);
    expect(retrivedData[0]).toEqual(mockArrayOfCategories[0]);
    expect(retrivedData[1]).toEqual(mockArrayOfCategories[1]);
  });

This is my unittest (getCategories.spec.ts)

import { TestBed, fakeAsync, inject, tick } from '@angular/core/testing';
import { MockBackend, MockConnection } from '@angular/http/testing';
import { BaseRequestOptions, Http, Response, ResponseOptions } from '@angular/http';

import { SiteService } from './siteService.service';
import { HierarchyItem } from '../../models/HierarchyItem';
import { hasLifecycleHook } from '@angular/compiler/src/lifecycle_reflector';
import { Category } from '../../models/Category';

describe('SiteService', () => {
  let siteService: SiteService;
  let mockBackend: MockBackend;

beforeEach(() => {
  TestBed.configureTestingModule({
    providers: [
      SiteService,
      MockBackend,
      BaseRequestOptions,
    {
      provide: Http,
      useFactory: (backend: MockBackend, defaultOptions: BaseRequestOptions) => {
        return new Http(backend, defaultOptions);
      },
      deps: [MockBackend, BaseRequestOptions]
    }
  ]
});
});

beforeEach(inject([
  SiteService,
  MockBackend
], (_siteService: SiteService,
_mockBackend: MockBackend) => {

  siteService = _siteService;
  mockBackend = _mockBackend;
}));

afterEach(() => {
  mockBackend.verifyNoPendingRequests();
});

describe('getCategories', () => {
  it('should return an Observable<Array<Category>> containing 2 categores; A and B', fakeAsync(() => {
  // Arrange
  const mockArrayOfCategories = new Array<Category>();
  let mockCategory = new Category();
  mockCategory.name = 'categoryA';
  mockArrayOfCategories.push(mockCategory);

  mockCategory = new Category();
  mockCategory.name = 'categoryB';
  mockArrayOfCategories.push(mockCategory);

  const response = new Response(new ResponseOptions({
    body: { value: mockArrayOfCategories }
  }));
  mockBackend.connections.subscribe((connection: MockConnection) => connection.mockRespond(response));

  // Act
  const categorySubscription = siteService.getCategories({ category: 'all' });
  tick();

  // Assert
  return categorySubscription.subscribe((retrivedData) => {
    expect(retrivedData.length).toBe(2);
    expect(retrivedData[0]).toEqual(mockArrayOfCategories[0]);
    expect(retrivedData[1]).toEqual(mockArrayOfCategories[1]);
  });

}));
});
});

and the method being tested

getCategories(context: SiteContext): Observable<Array<Category>> {
    return this.http.get(routes.getCategories(context), { cache: true })
      .map((res: Response) => <Array<Category>>res.json().Categories)
      .do(data => console.log(data))
      .catch(this.handleError);
  }

Upvotes: 0

Views: 228

Answers (0)

Related Questions