Angular 2 - Mocking - response is null

你离开我真会死。 提交于 2020-01-05 04:05:12

问题


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;
    }
}

回答1:


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);
});


来源:https://stackoverflow.com/questions/39893172/angular-2-mocking-response-is-null

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!