Last active
January 25, 2023 14:02
-
-
Save joeskeen/9594ce9642bc2166b8e21cec93725763 to your computer and use it in GitHub Desktop.
Different ways to use Jest to test error cases in Observable streams
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Observable, firstValueFrom, timer, isObservable, of } from "rxjs"; | |
import { first, timeout, catchError } from "rxjs/operators"; | |
import { TestScheduler } from "rxjs/testing"; | |
describe("testing error cases in Jest", () => { | |
describe("with RxJS", () => { | |
/** | |
* A test utility function for converting an Observable into a Promise for unit tests | |
* Uses a TestScheduler to make things like the passage of time (timeouts, debounce, etc.) | |
* happen instantaneously. | |
* | |
* @param action the action to perform (usually returning an Observable) | |
* @returns a Promise that will resolve on the first emitted value of the Observable | |
*/ | |
function schedule(action: Function): Promise<any> { | |
const scheduler = new TestScheduler((actual, expected) => | |
expect(actual).toEqual(expected) | |
); | |
return new Promise<void>((resolve, reject) => { | |
scheduler.run((helpers) => { | |
try { | |
let result = action(); | |
if (isObservable(result)) { | |
// if using newer versions of RxJS: | |
result = firstValueFrom(result); | |
// if using older versions of RxJS: | |
// result = result.pipe(first()).toPromise(); | |
} | |
helpers.flush(); | |
resolve(result); | |
} catch (err) { | |
reject(err); | |
} | |
}); | |
}); | |
} | |
describe("when timeout expires", () => { | |
function failsTimeout() { | |
return timer(1000000).pipe(timeout(10000)); | |
} | |
it("should throw", () => { | |
const promise = schedule(() => failsTimeout()); | |
expect(promise).rejects.toThrow(); | |
}); | |
}); | |
describe("when some error handling occurs", () => { | |
function failsTimeout(errorHandler: (err: any) => Observable<any>) { | |
return timer(1000000).pipe( | |
timeout(10000), | |
catchError((err) => errorHandler(err)) | |
); | |
} | |
let expectedResult: any; | |
let actualResult: any; | |
let handler: jest.Mock; | |
beforeEach(async () => { | |
expectedResult = {}; | |
handler = jest.fn(() => of(expectedResult)); | |
actualResult = await schedule(() => failsTimeout(handler)); | |
}); | |
it("should call the error handler", () => { | |
expect(handler).toHaveBeenCalled(); | |
}); | |
it("should get the result of the error handling", () => { | |
expect(actualResult).toEqual(expectedResult); | |
}); | |
}); | |
}); | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment