Logo

dev-resources.site

for different kinds of informations.

Mock modules properly with Jest and Typescript

Published at
2/17/2024
Categories
testing
jest
typescript
mock
Author
mattiz
Categories
4 categories in total
testing
open
jest
open
typescript
open
mock
open
Author
6 person written this
mattiz
open
Mock modules properly with Jest and Typescript

Jest provides a comprehensive suite of features designed to easily mock JavaScript modules.
At its core lies a concept that many developers will struggle with, if they haven't read carefully the documentation: the hoisting of mocks.
This often leads to unnecessary long and messy mock-related code, strange errors, and poor typings.
This article exposes the best way to succinctly and efficiently mock an ESM module, with strong typings.

How do I do it?

For the readers in a hurry, here you have it:



import { foo } from 'some-module' // Mocked module

jest.mock('some-module')

const mockFoo = jest.mocked(foo)


Enter fullscreen mode Exit fullscreen mode

jest.mocked() is only avaivable in Jest v27+.
Be sure you have installed @types/jest in your project, otherwise Typescript may not be aware of it.
๐ŸŒต Do not confuse it jest.mocked() with jest.mock()!

For older versions of Jest, use the form below, which will work in any version of Jest with Typescript support.



import { foo } from 'some-module' // Mocked module

jest.mock('some-module')

const mockFoo = foo as jest.MockedFunction<typeof foo>


Enter fullscreen mode Exit fullscreen mode

You can then ensure your mock is properly typed by using mockReturnValue



mockFoo.mockReturnValue(1) // Works
mockFoo.mockReturnValue('a') // Typescript error: foo must return a number

Enter fullscreen mode Exit fullscreen mode




Under the hood

Understanding what happens will prevent you some headaches in the future.

Did you ever wonder why Jest is called like this?
While the authors did not state why this exact name why chosen, I like to think that it is because the framework likes to "mock" and do tricks. ๐Ÿคก
In our example, Typescript is the victim. ๐Ÿ˜ข

Jest mock hoisting

Jest hoists mocks
Jest processes the mocks definitions before the imports.
This process is called mock hoisting and can be confusing at first.
๐Ÿจ Tips: I like to add the // Mocked module comment next to the mocked import, to make it obvious to everybody that we are dealing with a mocked module.

jest.mock() replaces all functions of the module by mock functions
You therefore don't need to define those mocks by hand.
Thanks to mock hoisting, you can import them through the usual import keyword.

Typescript needs helps
Typescript does not know about Jest's hoisting shenanigans; and think the function is imported without alterations.
There are various ways to hint Typescript that the function is a mock, depending on your needs and your preferences.



// A bit verbose, but works everywhere.
const mockFoo = foo as jest.MockedFunction<typeof foo>

// Equivalent to the 1rst form.
// From jest 27+
const mockFoo = jest.mocked(foo)

// A less verbose form, but you won't benefit from type-checking when mocking the returned value.
const mockFoo = foo as jest.Mock

// For one-time use, if you want to save a line not creating a variable.
jest.mocked(foo).toHaveBeenCalled()

// For one-time use ๐Ÿคฎ
;(foo as jest.Mock).toHaveBeenCalled()

Enter fullscreen mode Exit fullscreen mode




Scope

In this article, in order to bring the focus on principles linked to writing and typing Jest mocks, the focus was on ESM modules, with exported named functions.
This is probably the most common form of modules that you'll encounter, when consuming a library.
Mocking CommonJs (require), default exports or classes could be covered in an future article.

mock Article's
30 articles in total
Favicon
FAQ โ€” Bloomer Mock Data Generator
Favicon
Best Practices: How to Make Your API Smarter and More Flexible
Favicon
Testing ReactJS Context - A Guide with test-doubles
Favicon
The beauty of MSW
Favicon
Realistic data Generation Using Bloomer Mock
Favicon
Testing Spring Boot Applications: Unit, Integration, and Mocking โ€” A Comprehensive Guide
Favicon
How to debug your Python mocks or imports
Favicon
Is there any option for Mock EncryptAsync() in Azure.Security.KeyVault.Keys.Cryptography
Favicon
Learn to Simulate Online APIs Without Server Infrastructure
Favicon
Diferenรงas entre o jest.spyOn e jest.mock
Favicon
Mock Class Constructor in Jest Test with Mocking Partials
Favicon
You stub/mock incorrectly
Favicon
Step-by-Step Tutorial on Setting Up a Mock Server Using Postman
Favicon
Mocking ES6 Class Instances with Jest
Favicon
Create free mock apis with unlimited storage
Favicon
Free API server with unlimited access
Favicon
Handle Variables and Dynamic Values with `jest.fn()`
Favicon
A way to mock PHP internal functions with xepozz/internal-mocker
Favicon
Mock vs Stub vs Fake: Understand the difference
Favicon
Mock modules properly with Jest and Typescript
Favicon
Simplified Strategies for Mocking API Calls
Favicon
Fastify Meets WireMock: External Service Mocking
Favicon
OpenAI API Mock for Devs on a Budget
Favicon
Mock S3 for AWS SDK for JavaScript (v3)
Favicon
Simplifying Kafka Testing in Python: A Mockafka-py Tutorial
Favicon
When to use Mock API?
Favicon
Datafaker: Simplifying Test Data Generation for Java and Kotlin
Favicon
NestJS: Mocking Databases for Efficient Tests
Favicon
Understanding Mocks, Stubs, and Fakes in Software Testing
Favicon
How to Typescript to JSON with Butlermock

Featured ones: