diff --git a/README.md b/README.md index a6461ac..9cf6faf 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ and pairing with smart people at Hashrocket. For a steady stream of TILs, [sign up for my newsletter](https://tinyletter.com/jbranchaud). -_935 TILs and counting..._ +_936 TILs and counting..._ --- @@ -354,6 +354,7 @@ _935 TILs and counting..._ - [String Interpolation With Template Literals](javascript/string-interpolation-with-template-literals.md) - [Support Nested Matching In Custom Jest Matchers](javascript/support-nested-matching-in-custom-jest-matchers.md) - [Test Coverage Stats With Jest](javascript/test-coverage-stats-with-jest.md) +- [Test Timing-Based Code With Jest Fake Timers](javascript/test-timing-based-code-with-jest-fake-timers.md) - [The Comma Operator](javascript/the-comma-operator.md) - [Throttling A Function Call](javascript/throttling-a-function-call.md) - [Timing Processes](javascript/timing-processes.md) diff --git a/javascript/test-timing-based-code-with-jest-fake-timers.md b/javascript/test-timing-based-code-with-jest-fake-timers.md new file mode 100644 index 0000000..7989842 --- /dev/null +++ b/javascript/test-timing-based-code-with-jest-fake-timers.md @@ -0,0 +1,58 @@ +# Test Timing-Based Code With Jest Fake Timers + +In real-world code we use timeouts to do things like debouncing and throttling +of functions. This is really hard to test efficently and accurately with basic +test runner tooling. + +Jest, however, offers some [Timer Mock +tooling](https://jestjs.io/docs/en/timer-mocks) that removes most of the +complexity of getting this right. + +Here is a method to test: + +```javascript +const doSomethingAfter200ms = doSomething => { + setTimeout(() => { + doSomething(); + }, 200); +}; +``` + +A test that shows this to work would have to observe `doSomething` getting +called after 200ms. + +The following test won't work because the expectation is evaluated before the +timeout function is triggered. + +```javascript +describe("doSomethingAfter200ms", () => { + test("does something after 200ms (fail)", () => { + const doSomething = jest.fn(); + + doSomethingAfter200ms(doSomething); + + expect(doSomething).toHaveBeenCalled(); + }); +}); +``` + +By activating `jest.useFakeTimers()`, we can simulate the passing of 200ms and +then check that our mocked function was called. + +```javascript +jest.useFakeTimers(); + +describe("doSomethingAfter200ms", () => { + test("does something after 200ms (pass)", () => { + const doSomething = jest.fn(); + + doSomethingAfter200ms(doSomething); + + jest.advanceTimersByTime(201); + + expect(doSomething).toHaveBeenCalled(); + }); +}); +``` + +Jest's function mocks and timer mocks make this possible.