Let's say I have a component that subscribes to a service function:
export class Component {
...
ngOnInit() {
this.service.doStuff().subscribe(
(data: IData) => {
doThings(data);
},
(error: Error) => console.error(error)
);
};
};
The subscribe call takes two anonymous functions as parameters, I've managed to set up a working unit test for the data function but Karma won't accept coverage for the error one.
I've tried spying on the console.error function, throwing an error and then expecting the spy to have been called but that doesn't quite do it.
My unit test:
spyOn(console,'error').and.callThrough();
serviceStub = {
doStuff: jasmine.createSpy('doStuff').and.returnValue(Observable.of(data)),
};
serviceStub.doStuff.and.returnValue(Observable.throw(
'error!'
));
serviceStub.doStuff().subscribe(
(res) => {
*working test, can access res*
},
(error) => {
console.error(error);
console.log(error); //Prints 'error!' so throw works.
expect(console.error).toHaveBeenCalledWith('error!'); //Is true but won't be accepted for coverage.
}
);
What's the best practice for testing anonymous functions such as these? What's the bare minimum to secure test coverage?
You can simply mock Observable throw error object like
Observable.throw({status: 404})
and test error block of observable.Not sure exactly the purpose of the code you are showing, which is trying to test a mock service. The coverage problem is with the component and the error callback to not have been called (which is only called when there is an error).
What I usually do for most of my observable services, is to create a mock whose methods just returns itself. The mock service has a
subscribe
method that accepts thenext
,error
, andcomplete
callbacks. The user of the mock gets to configure it to add an error so theerror
function gets called, or add data, so thenext
method gets called. The thing I like most about this is that it's all synchronous.Below is something like what I normally use. It's just an abstract class for other mocks to extend. It provides the basic functionality that an observable provides. The extending mock service should just add the methods it needs, returning itself in the method.
Now in your tests you just do something like