0

I have read many questions here and a few tutorials and I still can't get this working, I've copied the tutorials word-for-word and still no luck so I have no idea what the issue is. I'm pretty new to this stuff. Here's my code:

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

import { ItemsService } from './items.service';
import { MOCKITEMS } from './mock-items';

describe('ItemsService', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [HttpModule],
      providers: [ItemsService]
    });
  });

  it('should construct', inject([ItemsService], (service) => {
      expect(service).toBeDefined();
  }));
});

describe('ItemsService Mock', () => {
  beforeEach(() => {
    TestBed.configureTestingModule({
      providers: [
        ItemsService,
        MockBackend,
        BaseRequestOptions,
        {
          provide: Http,
          useFactory: (backend, opts) => new Http(backend, opts),
          deps: [MockBackend, BaseRequestOptions]
        }
      ],
      imports: [HttpModule]
    });
  });

  it('should construct', inject([ItemsService, MockBackend], (service, mockBackend) => {
    expect(service).toBeDefined();
  }));

  describe('#getItems()', () => {
    it('should return <Array<Items>>', inject([ItemsService, MockBackend], (service, mockBackend) => {
      const mockReponse = {
        data: [
          { itemCharId: 1, itemName: 'milk' },
          { itemCharId: 2, itemName: 'eggs' },
          { itemCharId: 3, itemName: 'meat' }
        ]
      }

      mockBackend.connections.subscribe((connection) => {
        connection.mockRespond(new Response(new ResponseOptions({ body: JSON.stringify(mockReponse) })));
      });

      service.getItems().subscribe((items) => {
        expect(items.length).toBe(3);
        expect(items[0].itemName).toEqual('milk');
        expect(items[1].itemName).toEqual('eggs');
        expect(items[2].itemName).toEqual('meat');
      });
    }));
  });
});

The tests are failing with expected undefined to be 3, etc. So I'm assuming it's not actually getting my mockResonse obj as the response or something on those lines? Could just be something small too I guess.

Service code:

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

@Injectable()
export class ItemsService {

  constructor(private http: Http) { }

  getItems() {
    return this.http.get('/api/items');
  }
}

Any help greatly appreciated.

2
  • Could just be something small too I guess - I wouldn't call the absence of service code small. It's quite huge. Please, provide all relevant code. It's necessary to get an idea on what you're testing. Commented May 10, 2017 at 0:18
  • Added service code in main post Commented May 10, 2017 at 1:03

1 Answer 1

2

In the tutorial that was likely was followed, service method returns response.json().data:

  getHeroes(): Promise<String[]> {
    return this.http.get('myservices.de/api/heroes')
        .toPromise()
        .then(response => response.json().data)
        .catch(e => this.handleError(e));
  }

So the response is mocked as { data: [...] }.

While in the example in the question it returns this.http.get('/api/items') and doesn't call response.json().

These are the reason why there are no errors except failed assertions; items has to be equal to mockReponse.

It should be

  getItems() {
    return this.http.get('/api/items').map(res => res.json());
  }

and

  const mockReponse = [
      { itemCharId: 1, itemName: 'milk' },
      { itemCharId: 2, itemName: 'eggs' },
      { itemCharId: 3, itemName: 'meat' }
  ]

This can additionally be asserted with

expect(items).toEqual(mockResponse);
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks for your help. I tried that and it's still giving me the same failures. The actual service just returns an array like you listed above so that's how I would like to get this working.
I'm not sure what's the problem. You expect items to be array, and you need mockResponse to be an array too (not an object with data property). Then it should work. Actually, you can add expect(items).toEqual(mockResponse), because it's true and will provide better feedback in the case of assertion failure.
I'm quite new to webdev so there could be something extremely obvious that I have wrong :) Here's the error message using toEqual: Expected Response with status: null null for URL: null to equal [ Object({ itemCharId: 1, itemName: 'milk' }), Object({ itemCharId: 2, itemName: 'eggs' }), Object({ itemCharId: 3, itemName: 'meat' }) ]. Could that mean my getItems method isn't getting the data from the api?
Sure, now I see that. I assumed that the service is working fine in production, but it cannot work like that. You forgot to call res.json(). I updated the answer. You also need to have rxjs/add/operator/map in service file for map observable operator in order for this to work.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.