How to Mock Functions Per Test in TypeScript And Jest

Apr 16, 2023

Have you ever had the need for updating the UI based on an underlying hook or function in a unit test? Then this tidbit might be just right for you.

I recently came across this issue, the solution was quite simple, just make a mock implementation of the underlying function and change the received values - right?

Yes and no - the solution works but Typescript isn't too happy.

The reason is that Typescript does not automatically assign the mocked capabilities to the original function after using jest.mock to overwrite the implementation. There is no automatic inheritance.

import { useFeatureFlags } from 'hooks/useFeatureFlags'

jest.mock('hooks/useFeatureFlags')

// ERROR: Property 'mockImplementation' does not exist on type [useFeatureFlag]
useFeatureFlags.mockImplementation(() => ({
  MY_FEATURE_FLAG: true
}))

Sadly, this is one of the instances where Jest and TypeScript aren't the best of friends and we will have to cast the desired implementation ourselves. Luckily, Jest comes with the type of MockedFunction as a generic. We can then easily slot in our original function type with the typeof interpreter. We will have to store the mocked function on its own variable to get the best effect, this will also show the correct intent for the next person viewing the code.

import { useFeatureFlags } from 'hooks/useFeatureFlags'

jest.mock('hooks/useFeatureFlags')
const useFeatureFlagsMock = useFeatureFlags as jest.MockedFunction<typeof useFeatureFlags>

We can now use the jest capabilities to mock the outcome of the function.

useFeatureFlagsMock.mockImplementation(() => ({
  MY_FEATURE_FLAG: true
}))

It is now possible to get different UI states based on the mocked functions return value, within single test cases or within different scopes. Here is a contrived example with all of the above together.

import { useFeatureFlags } from 'hooks/useFeatureFlags'

jest.mock('hooks/useFeatureFlags')
const useFeatureFlagsMock = useFeatureFlags as jest.MockedFunction<typeof useFeatureFlags>


describe('feature flag test', () => {
  it('should show if feature flag is on', async () => {
		useFeatureFlagsMock.mockImplementation(() => ({
		  MY_FEATURE_FLAG: true
		}))

		...
  })

  it('should not show if feature flag is on', async () => {
		useFeatureFlagsMock.mockImplementation(() => ({
		  MY_FEATURE_FLAG: true
		}))

    ...
  })
})

You can of course throw this into a beforeEach method or do whatever else you usually would do with Jest to achieve your test completion.