Mocking a JavaScript class with Jest: mocking vs. dependency injection
In all the tests I&#x27;ve written mocking always sucks. It&#x27;s not hard, but it becomes a rabbit whole time suck.<p>My personal goal is to only mock the server and as low as possible or necessary.<p>I&#x27;m fully convinced mocking is a code smell of a bad implementation. It means the abstraction is leaky or too complex and would be better off being broken further down. I also abide by the rule of not exporting or making something public just for the sake of testing it.<p>Property tests are useful but can be tricky to identify, and a good type system that is well used removes the need for the majority of unit tests. No more, validate this function returns a number, or a string. The compiler will test and guarantee that for you.<p>Invoke the function under test and assert on its return value. This works in the majority of cases but when you do need to reach for something stronger, JS can do some fun stuff via reflection.<p>An example.<p>We want to test a function that consumes an object which is used to make an HTTP fetch call, building the `Request` object from the passed object.<p><pre><code>    &#x2F;&#x2F; Of course we mock the fetch function 
    &#x2F;&#x2F; or would have a mock server running via something like msw. 
    &#x2F;&#x2F; Tests should never require an internet connection to run.

    window.fetch = jest.fn().mockResolveValue(new Response());

    const config = { url: &#x27;https:&#x2F;&#x2F;myapi.com&#x27; };

    &#x2F;&#x2F; Invoke the function under test
    await myFunctionThatInvokesFetch(config);

    &#x2F;&#x2F; We can access the mocked fetch function and get the argument with which it was called - 
    &#x2F;&#x2F; the built up Request object from the argument passed to the function under test.
    const requestObjectUsed = window.fetch.mock.calls[0][0];
    const realRequestObject = new Request(requestObjectUsed);
    
    &#x2F;&#x2F; Validate that if no method is specified in config, we default to a GET request.
    expect(realRequestObject.method).toBe(&#x27;GET&#x27;);
</code></pre>
Lastly, if a function modifies one of its arguments, the function should include that modified value as part of it&#x27;s return value. The same could be said for having a function invoke other functions. Rather than assert a function is called, have it return something that indicates it was called.<p>This makes testing a breeze and is also a hint to the invoker that something was done to the thing passed to it.