1

Angular 2.0.0 - Ionic 2 RC0 - Npm 3.10.8 - Node v4.5.0 - Karma 1.3.0 - Jasmine 2.5.2

previous question: Angular 2 -- Mocking - No Provider for HTTP


I'm now getting a new error while executing npm test : null is not an object (evaluating '_this.events.length')

Which is triggered by this code: if(this.events.length > 0){ in EventsPage which means my response I set in events.spec.ts is somehow not properly returned.

I'm new to mocking Angular2 so it's moest likely a rookie mistake.

(changed some code from previous question, so I'll repost them)

EventPage

import { Component } from '@angular/core';

import { NavController, Loading, LoadingController } from 'ionic-angular';

import { APICaller } from '../../services/apicaller.service';
import { EventDetailComponent } from '../event-detail/event-detail.component';
import { Event } from '../../models/event.model';

/*
  Class for Evenementen Overzicht.
*/
@Component({
  selector: 'events-component',
  templateUrl: 'events.component.html',
  providers: [ APICaller ]
})

 /** -------------------------------------------------------------------------------------- */

    export class EventsPage {

    //list of all events
    public events : Array<Event>;
    //the event that has been clicked on the page
    public selectedEvent : Event;
    //boolean to show 'no events' error message
    public noEvents:boolean;

     /** -------------------------------------------------------------------------------------- */

      constructor(public navCtrl : NavController, public apiCaller:APICaller, public loadingCtrl : LoadingController) {
        //retrieve all events --> async method, can't use this.events yet.
        this.getEvents();
      }

      /** -------------------------------------------------------------------------------------- */

      /**Get Events - Sets the 'events' variable to all events found by the API. */
      getEvents(){
        //setup a loadingscreen (broke testing so removed for now)
       // let loading = this.loadingCtrl.create({
        //  content: "Loading..."
       // }); 
        //present the loadingscreen
       // loading.present();

        //reset the noEvents boolean.
        this.noEvents = true;

        //call the api and get all events
        this.apiCaller.getEvents()
        .subscribe(response => {

          console.log("RESP:"+response);
          //response is list of events
          this.events = response;
          //if the event is not empty, set noEvents to false.

          if(this.events.length > 0){ //<----------------------------FAILS HERE
            this.noEvents = false;
          }
          //close the loading message.
         // loading.dismiss();
        });
      }
    }

EventPage -- Spec

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

import { FormsModule } from '@angular/forms';
import { NavController, LoadingController } from 'ionic-angular';
import { CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
import { mockNavController, mockApp } from 'ionic-angular/util/mock-providers';
import { EventsPage } from './events.component';
import { MockAPICaller } from '../../services/mocks/apicaller.service';
import { APICaller } from '../../services/apicaller.service';


describe('Component: EventsComponent', () => {
  let mockAPICaller : MockAPICaller = new MockAPICaller();
  let loadingCtrl : LoadingController = new LoadingController(this);

  beforeEach(() => {
  TestBed.configureTestingModule({
    declarations: [EventsPage],
    schemas: [CUSTOM_ELEMENTS_SCHEMA],
    providers: [
      {provide: APICaller, useValue: mockAPICaller},
      {provide: NavController, useValue: mockNavController },
      {provide: LoadingController, useValue: loadingCtrl},
    ],
    imports: [FormsModule]
  });

  TestBed.overrideComponent(EventsPage,{
    set: {
      providers: [
        {provide: APICaller, useValue: mockAPICaller}
      ]
    }
  });
  });


  it('should return all events', () => {

      let fixture = TestBed.createComponent(EventsPage);
      let eventsPage = fixture.debugElement.componentInstance;
      fixture.detectChanges();

      mockAPICaller.setResponse(JSON.stringify(`[{
        id: 4,
        title: 'Weekend',
        eventdate: '24/09/2016',
        kind: 'closed',
        startingtime: '18:00',
        endtime: '21:00',
        description: 'Go Home'
      }]`));
      eventsPage.getEvents();
      fixture.detectChanges();
      console.log(eventsPage.events);

  });
});

MockAPICaller

import { SpyObject } from './helper';
import { APICaller } from '../apicaller.service';
import Spy = jasmine.Spy;

export class MockAPICaller extends SpyObject {
    getEventsSpy: Spy;
    searchEventSpy:Spy;
    getParticipantSpy:Spy;
    getEventParticipantsSpy:Spy;
    searchEventParticipantSpy:Spy;
    addNewCommentSpy:Spy;
    updateCommentSpy:Spy;
    deleteCommentSpy:Spy;
    getUsernameSpy:Spy;
    presentSuccessMessageSpy:Spy;

    fakeResponse:any;

    constructor(){
        super( APICaller );
        this.fakeResponse = null;
        this.getEventsSpy = this.spy('getEvents').andReturn(this);
        this.searchEventSpy = this.spy('searchEvent').andReturn(this);
        this.getParticipantSpy = this.spy('getParticipant').andReturn(this);
        this.getEventParticipantsSpy = this.spy('getEventParticipant').andReturn(this);
        this.searchEventParticipantSpy = this.spy('searchEventParticipant').andReturn(this);
        this.addNewCommentSpy = this.spy('addNewComment').andReturn(this);
        this.updateCommentSpy = this.spy('updateComment').andReturn(this);
        this.deleteCommentSpy = this.spy('deleteComment').andReturn(this);
        this.getUsernameSpy = this.spy('getUsername').andReturn(this);
        this.presentSuccessMessageSpy = this.spy('presentSuccessMessage').andReturn(this);
    }

    subscribe(callback: any){
        callback(this.fakeResponse);
    }

    setResponse(json:any):void{
        this.fakeResponse = json;
    }
}
Community
  • 1
  • 1
Ivar Reukers
  • 7,560
  • 9
  • 56
  • 99

1 Answers1

0

You should set the response on the mock before creating the component. You are calling getEvents in the component constructor, and the mock hasn't set the data yet.

it('should return all events', () => {
  mockAPICaller.setResponse(JSON.stringify(`[{
    id: 4,
    title: 'Weekend',
    eventdate: '24/09/2016',
    kind: 'closed',
    startingtime: '18:00',
    endtime: '21:00',
    description: 'Go Home'
  }]`));
  let fixture = TestBed.createComponent(EventsPage);
  let eventsPage = fixture.debugElement.componentInstance;
  fixture.detectChanges();
  eventsPage.getEvents();
  fixture.detectChanges();
  console.log(eventsPage.events);
});
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720