Previously, we discovered how powerful vitest can be when used with vite.
Using mocks gives us the flexibility to simulate, develop, test, and refine use cases quickly and easily.
For mocking behavior in development and API integration I will use MSW.
For simple function business logic, I will demonstrate vitest mocking function.
Full code - https://github.com/yanirmanor/vite-test-vitest
For a simple function mock you will use
vi.fn()
then you have all kinds of functions that you can use and control the mock. The most popular I think is mockReturnValue for mocking the return value or mockImplementation for mocking the function implementation.
examples:
vi.fn().mockReturnValue(23)
expect(mockFnOverrideValue()).toBe(23)
const mockFnGetSum =
vi.fn().mockImplementation(sum => sum * 3.14)
const total = mockFnGetSum(100)
expect(total).toBe(314)
Nice. now I will show how you can use MSW for development and testing.
First install msw -
pnpm install msw --save-dev
then run
pnpx msw init public/ --save
In development - I created a vite .env variables VITE_MOCKING and set it to be true.
in the app.jsx I added an if statement, then you need to create and handlers a set of request mock.
you need to set the handlers array inside setupWorker and make it start.
you can open the network tab inside the chrome devtools
and look for the service worker in the response header.
also, you will see in devtools console - [MSW] Mocking enabled
if (import.meta.env.VITE_MOCKING === true) {
const handlers = [
rest.get('https://randomuser.me/api/', (req, res, ctx) => {
return res(
ctx.delay(1000),
ctx.status(202, 'Mocked status'),
ctx.json({
results: [
{
name: {
first: 'John',
last: 'Doe'
}
}
]
})
)
})
]
const worker = setupWorker(...handlers)
worker.start()
}
We have almost done.
this technique is similar for testing.
instead of using serviceWorker we will replace it with setupServer
and start this node server to run by listen() before all tests
, after all, we call close and finally on after each test we will reset
const server = setupServer(...restHandlers)
// Start server before all tests
beforeAll(() => server.listen({ onUnhandledRequest: 'error' }))
// Close server after all tests
afterAll(() => server.close())
// Reset handlers after each test `important for test isolation`
afterEach(() => server.resetHandlers())
With this approach, your tests will be cleaner and more readable, and your software will be developed more quickly.
Enjoy 😎
Top comments (5)
Thank you! Very helpful! :)
Is it me or this article/tutorial is missing details?
How we got from using simple vi.fn for mocking to
install MSW (what is this? And why should I care about it?
I neither understood what this is suppose to achieve, nor how to achieve it :(
This article is about mocking vitest and the great power that you will get if you are using msw as mocking api calls for integration testing. Integration testing are very more efficient than unit testing.
In this article you can see how easy it is to install and using it. Also, you can use it for development.
Then the title should be something like
vitest + MSW = 💪 superpower
instead ofvitest + mocks = 💪 superpower
And at least introduce the fact you are proposing to use an external package, not the vitest mocking functionality itself.
But for each their own.
No matter the approach taken, the Article title is misleading and the premise is unclear.
So you may want to edit that, to make it a bit more clear what you are proposing and explaining.
Have a good day
Thanks!