2

I am trying to test an async function in a simple Angular Application.

Using this component:

Component

import { Component, OnInit } from '@angular/core';
import { DataService } from '../../services/data.service';
import { Component, OnInit } from '@angular/core';
import { DataService } from '../../services/data.service';

@Component({
  selector: 'app-post',
  templateUrl: './post.component.html',
  styleUrls: ['./post.component.css']
})
export class PostComponent implements OnInit {
  public posts:Post[];

  constructor(public data:DataService) { }

  ngOnInit() {
    this.data.getPosts().subscribe((res) => this.posts = res);
  }
}

export class Post{
  public userId:number;
  public id:number;
  public title:string;
  public body:string;
}

I can retrieve, by a data service layer, a json posts list to fill the posts property of PostComponent class.

Service

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class DataService {

  constructor(public http: Http) { }

  getPosts() {
    return this.http.get('https://jsonplaceholder.typicode.com/posts').map(res => res.json());
  }
}

So I wrote this Jasmine test following this suggestion:

import { async, ComponentFixture, TestBed, fakeAsync } from '@angular/core/testing';
import { HttpModule } from '@angular/http';
import { DataService } from '../../services/data.service';
import { PostComponent } from './post.component';
import {Post} from '../post/post.component';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';

describe('PostComponent', () => {
  let component: PostComponent;
  let fixture: ComponentFixture<PostComponent>;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      imports: [
        HttpModule
      ],
      declarations: [PostComponent],
      providers: [DataService]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(PostComponent);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

  it('sholud call ngOnInit and fill Posts[]', async(() => {
    const foo:Post[] = [];

    const spy = spyOn(component, 'ngOnInit').and.returnValue(Observable.of(component.posts));
    component.ngOnInit();
    fixture.detectChanges();

    expect(component.posts.length).toBeGreaterThan(1);
  }));
});

but I get this error:

Failed: Cannot read property 'length' of undefined

TypeError: Cannot read property 'length' of undefined

How can I test it?

1 Answer 1

2

Resolved using this:

it('should call ngOnInit and fill Posts[]', () => {
    spyOn(component, "ngOnInit").and.callThrough();
    component.ngOnInit();
    fixture.detectChanges();

    fixture.whenStable().then(() => {
      expect(component.posts.length).toBeGreaterThan(0);
    });
 });
Sign up to request clarification or add additional context in comments.

Comments

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.