unit testing spyOn observable service in angular2
However, the test case doesn't work and throws "Error: No provider for Http!".
Because you still have the service in the providers
, so Angular is trying to create it still
providers: [
InteractWithServerService,
ChildService],
What you can do instead of creating a mock class is to just do something like
providers: [
{
provide: InteractWithServerService,
useValue: { get: Observable.of(..) }
}
]
Here's you're using useValue
which provide any object. That will be the value used when injected. In the case above, it is just some arbitrary object with your mock method.
If you want to spy so that you can provide different values, you could inject the InteractWithServerService
, and then do
spyOn(service, 'get').and.returnValue(Observable.of(...))
// do test
Another thing you could do is mock the Http with a dummy object
{ provide: Http, useValue: {} }
Now the InteractWithServerService
will work (just adding the class to the providers` like you currently have). And you can just spy on it
let service = TestBed.get(InteractWithServerService);
spyOn(service, 'get').and.returnValue(..)
// do test
Another more elegant way I found is to spy on the observable property and return a value, after which you flush within a fakeAsync. This will allow you to test the code inside your subscribe.
Simplified Version
.ts File
private isThereWork(): void {
this.subscription.add(this.work$
.subscribe((hasWork: boolean) => {
this.displayWorkItems = hasWork;
})
);
}
.spec.ts
fit('should work be displayed', fakeAsync(() => {
spyOnProperty<any>(component, 'work$', 'get').and.returnValue(of(false));
component['isThereWork']();
flush();
expect(component.displayWorkItems ).toBe(false);
}));
Hope this helps. I thought this a game changer when I found out.
Using jasmin 2.6.2: get
is a function so you need to add the arrow function notation to the answer above:
providers: [
{
provide: InteractWithServerService,
useValue: { get: () => Observable.of(..) }
}
]