2

I am trying to write some unit-tests on a component that got some services injected into it, to load the data from server. Data is loaded in this component on OnInit() method. I am trying that service method returns some dummy data, using spyOn. Following is unit-test setup -

let comp: MyComponent;
let fixture: ComponentFixture<MyComponent>;
let staticDataService: any;
let spy: jasmine.Spy;
let allCountries: string[];

describe('MyComponent', () => {
beforeEach( async(() => {

    TestBed.configureTestingModule({
        imports : [ FormsModule, HttpModule ],
        declarations : [MyComponent],
        providers: [ StaticDataService ]
    })
    .compileComponents();
}));

beforeEach(() => {
    fixture = TestBed.createComponent(MyComponent);
    comp = fixture.componentInstance;
    staticDataService = fixture.debugElement.injector.get(StaticDataService);
    allCountries = [] = ["US", "UK"];
    spy = spyOn(staticDataService, 'getCountries').and.returnValue(Promise.resolve(allCountries));
    });
it('Countries should be set', () => {
    expect(comp.allCountries).toEqual(allCountries);
    }); 
});

Following is the component class that I am unit-testing -

@Component({
  moduleId: module.id,
  selector: 'myeditor',
  templateUrl: 'my.component.html',
  styleUrls: ['my.component.css']
})
export class MyComponent implements OnInit {
  allCountries: string[];
  constructor(private _staticDataServices: StaticDataService) {}
  ngOnInit() {
    this.getDataFromServer();
  }

  getDataFromServer()
  {
    this.allCountries = this._staticDataServices.getCountries();
  }

I am getting the following error -

    Chrome 53.0.2785 (Windows 7 0.0.0) MyComponent Countries should be set FAILED
    [1]     Expected undefined to equal [ 'US', 'UK' ].

Under the same unit-tests few other tests are working fine, that are not dependent on injected services. Getting 'undefined' while testing the properties that are set by services. Can someone please help what I am doing wrong here?

Thanks

Raj
  • 127
  • 2
  • 9

1 Answers1

0
  1. You need to call fixture.detectChanges() for the ngOnInit to be called.

    fixture = TestBed.createComponent(MyComponent);
    fixture.detectChanges();
    
  2. getCountries returns a Promise so you need to then it, otherwise the value of allCountries will just be promise and not the data

    getDataFromServer() {
      this._staticDataServices.getCountries().then(data => {
        this.countries = data;
      });
    }
    
  3. Since the promise is asynchronous, you need to use async and wait for the asynchronous task to complete by calling fixture.whenStable()

    import { async } from '@angular/core/testing';
    
    it('...', async(() => {
      fixture.whenStable().then(() => {
        expect(comp.allCountries).toEqual(allCountries);
      })
    })
    

UDPATE

Without seeing the StaticDataService, I'm guessing you are trying to inject Http into it. This wont work in a test environment without further configuration. What I suggest you do is just make the service a mock

staticDataService = {
  getCountries: jasmine.createSpy('getCountries').and.returnValue(...);
}

providers: [
  { provide: StaticDataService, useValue: staticDataService }
]
Paul Samsotha
  • 205,037
  • 37
  • 486
  • 720
  • Thanks for the response. When I apply these changes I am getting the following error - – Raj Oct 17 '16 at 02:08
  • Thanks for the response. When I apply these changes I get the following error - [1] TypeError: this._staticDataService.getCountries(...).subscribe is not a function Not sure why this method is getting called when it should be overridden by the method/values specified in spyOn. – Raj Oct 17 '16 at 02:27
  • You can't call `subscribe` on a promise (which is what the mock is returning). That is only for observables. They are different things. You need to call `then` on a promise. If you want to emit an observable instead in your mock, then `and.returnValue(Observable.of(allCountries))` – Paul Samsotha Oct 17 '16 at 02:30
  • You will need to import `rxjs/add/observable/of` – Paul Samsotha Oct 17 '16 at 02:31
  • Thanks, that helps. It passed thru OnInit method. Further need to resolve some html parsing errors appearing in same tests.. – Raj Oct 17 '16 at 02:36