How to test a Typescript app using vitest and msw
Sandro Maglione
Get in touch with meWeb development
24 November 2023
•7 min read
Sandro Maglione
Web development
In this article we are going to use vitest
in combination with msw
to test a Typescript application.
In the previous article I explained step by step how to use Effect to implement a Custom Newsletter form with ConvertKit.
In this article we are going to test the final implementation:
- Setup handlers and testing server with
msw
- Install and configure
vitest
- Learn how to mock HTTP requests
Installing and setting up msw
msw
(Mock Service Worker) is a library that allows to mock APIs.
In this example we use msw
to intercept and mock the response of HTTP requests. Instead of sending a request to the server, msw
allows to return mock data:
- Test app without interacting with any external service
- Verify correct behavior for all possible responses
Mocks
The first step is defining mocks for environmental variables and responses. We define all the mocks inside a new mocks.ts
file.
With Effect we can mock Config
by using ConfigProvider.fromMap
. This allows to provide mock values for environmental variables.
We then use Layer.setConfigProvider
to build a Layer
that we will later provide to each test:
We also need to create a mock for a SubscribeResponse
. This is a simple object used to mock a response:
Handlers
Our application performs some HTTP requests. While testing we do not want to send real requests, but instead we want to intercept them and return a mocked response.
This is exactly what msw
allows us to do using handlers.
We define a list of handlers in a new handlers.ts
file.
Each handler is defined using http
from msw
:
http.post
: Intercepts a POST request- The first parameter is the URL of the request to intercept (e.g.
"http://localhost:3000/forms/123/subscribe"
) - The second parameter is used to define a custom mocked response
msw
supports plain strings, wildcards (*
) and also regex for the URL parameter (Documentation)
Server setup
The last step with msw
is creating a server from handlers
.
This step is different based on the environment where we are running our tests:
- Node: Import
setupServer
from"msw/node"
- Browser: Import
setupWorker
from"msw/browser"
- React Native: Import
setupServer
from"msw/native"
In our case we are running the test on a Node environment:
There is more.
Every week I build a new open source project, with a new language or library, and teach you how I did it, what I learned, and how you can do the same. Join me and other 600+ readers.
Installing and setting up vitest
vitest
is a testing framework that provides an API to define and organize tests.
It is similar to jest
, it provides the same API, with methods like describe
, it
, etc.
Remember to also add "type": "module"
in package.json
(documentation):
tsconfig
paths
In our app we are using custom Typescripts paths defined inside tsconfig.json
:
We need to configure vitest
to resolve these custom paths. We install vite-tsconfig-paths
and add it as a plugin inside vitest.config.ts
:
Defining and running tests
We are now ready to write some tests.
msw
requires to open, reset and close the server we defined above. We can do this inside beforeAll
, afterEach
and afterAll
:
We use describe
to organize tests for specific functions and it
to implement the actual test:
- Define a valid
Request
- Use
layerConfigProviderMock
to provide mocks for environmental variables - Verify that the response is equal to the expected mock
subscribeResponseMock
In this test msw
intercepts the HTTP request and returns subscribeResponseMock
. This test passes since we provided all the valid configurations and parameters.
We can then verify also all other possible cases (missing body, wrong request method, invalid formatting, etc.):
In this second example the body is missing the required email
parameter. We therefore expect the response to be a formatting error.
This is all you need to test your app!
By using vitest
+ msw
we have a powerful testing API at our disposal, as well as a complete API and mocking library.
We are in complete control of all the services and requests. This allows to mock and verify all possible situations and responses.
Indeed testing can be fun and definitely satisfying!
If you are interested to learn more, every week I publish a new open source project and share notes and lessons learned in my newsletter. You can subscribe here below 👇
Thanks for reading.