From 90ee653940c0dbc355e69758f680dca893efe24e Mon Sep 17 00:00:00 2001 From: kevinb-khan Date: Wed, 10 Jul 2024 17:41:19 -0400 Subject: [PATCH] Provide an example of how to mock singletons in jest tests (#14) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary: This is the last bit of feedback that needed to be addressed. This PR provides and example in content.mdx for Lesson 3 that demostrates how to structure a singleton so that it can be easily mocked in jest tests. Issue: None ## Test plan: - yarn dev - http://localhost:5173/react-render-perf/lesson-03 - see that the new content is formatted correctly Author: kevinb-khan Reviewers: beaesguerra Required Reviewers: Approved By: beaesguerra Checks: ✅ Lint (ubuntu-latest, 20.x), ✅ Prime node_modules cache for primary configuration (ubuntu-latest, 20.x), ✅ Lint (ubuntu-latest, 20.x), ✅ Prime node_modules cache for primary configuration (ubuntu-latest, 20.x) Pull Request URL: https://github.com/Khan/frontend-infra-workshops/pull/14 --- src/react-render-perf/lesson-03/content.mdx | 47 ++++++++++++++++++++- 1 file changed, 45 insertions(+), 2 deletions(-) diff --git a/src/react-render-perf/lesson-03/content.mdx b/src/react-render-perf/lesson-03/content.mdx index d88fd07..a4e327c 100644 --- a/src/react-render-perf/lesson-03/content.mdx +++ b/src/react-render-perf/lesson-03/content.mdx @@ -77,10 +77,53 @@ While singletons are sometimes frowned upon because they can make testing more difficult in some languages, that isn't the case in JavaScript. It's easy to mock the singleton using jest if follow these guidelines: -- Export the singleton from its own file. TODO(kevinb): provide an example of how to - mock the singleton. - If you have a custom class instead of using EventEmitter be sure to export that as well so that you can use it when mocking the singleton. +- Instead of exporting the singleton directly, export a function that returns the + singleton. This will allow you to mock the singleton on a per-test basis. + +```ts +// my-awesome-event-emitter.ts +export class MyAwesomeEventEmitter { + ... +} + +// This is our singleton. Note that it isn't being exported. +// Instead, we want people to use the function below to get +// the singleton. +const myAwesomeEventEmitter = new MyAwesomeEventEmitter(); + +export const getMyAwesomeEventEmitter = () => myAwesomeEventEmitter; +``` + +When writing tests you import both the class and the singleton getter into your test +file to help with mocking. + +```ts +// foo.test.ts +import * as MyAwesomeEventEmitter from "../my-awesome-event-emitter" + +describe("Foo", () => { + it("should function as expected", () => { + // Arrange + const mockEmitter = new MyAwesomeEventEmitter(); + // modify the state of mockEmitter if necessary. + jest.spyOn( + MyAwesomeEventEmitter, "getMyAwesomeEventEmitter" + ).mockReturnValue( + mockEmitter, + ); + // Now the code under test will be using `mockEmitter` instead of + // the `myAwesomeEventEmitter` that we created in my-awesome-event-emitter.ts. + + // Act + // ... + + // Assert + // ... + }); +}); +``` ### State