I've run into trouble in the past with testing observables, so I figured I would make myself a gist to help myself remember, and to help others who find it.
Observables are rather tricky to test in general as they are made to be asynchronous and act like a stream, and up until recently it was acceptable to pass a next
, error
, and complete
callback function, but now that method is bieng deprecated in favor of Observers
. Fear not! An Observer
is just like the three callbacks rolled into a signle object, plus other fields you would like to add :).
Say that we have the following Observable
const numbersArray = from([1,2,3,4,5]);
If we were to subscribe to this observable with a simple subscription and console.log
numbersArray.subscribe(value => console.log(value)).unsubscribe();
each value we would get the output
1
2
3
4
5
Now this is great and all, but we could instead give the subscribe function an observer like the following:
const numberObserver = {
sum: 0
next(value) {
this.sum += value;
},
error(error) {
throw error
},
complete() {
console.log(this.sum);
}
};
Now when we subscribe
numbersArray.subscribe(numberObserver).unsubscribe();
we get the sum of the values as the output
15
This is great to see how the Observer
works and how to easily take advantage of the object. Now in a testing situation, like with Jest
, you will want to call a callback function in your complete
method to tell Jest
that the test has finished. To still allow me to use pre-made observers, I create a factory-esque function that takes in the callback as a parameter. The function would look something like this:
const myObserver = (done) => {
next(value) {
//usually run your asserts here on single objects
},
error(error) {
// throw the error so jest will fail
throw error;
},
complete() {
// call the callback to signify that the test is compelte
done();
}
If you are testing for an error specifically you can use the following as well:
const myErrorObserver = (done, errorObject) => {
next(value) {
throw new Error('Expected no value but got ' + value + ' instead.');
},
error(error) {
expect(error).toEqual(errorObject);
},
complete() {
done();
}
};
You can always add more to the creation function to make your observers even more powerful while testing.