Mock responses
Loading "Mock Responses (π solution)"
Run locally for transcripts
First, I will delete the
http.all()
request handler in handlers.ts
:import { http } from 'msw'
export const handlers = [
http.all('*', ({ request }) => {
console.log(request.method, request.url)
}),
]
It was a great debugging handler to let us see all the outgoing requests in this test, but we will focus on intercepting particular requests right now.
In the same
handler.ts
module, I will create a new request handler for a POST
request to the https://api.example.com/auth
endpoint, using the http.post()
function:import { http } from 'msw'
export const handlers = [
http.post('https://api.example.com/auth', () => {
return Response.json({
token: 'abc-123',
})
}),
]
To mock a response to the intercepted request, I am returning a Fetch API
Response
instance from its response resolver (the second argument of the request handler: http.post(path, resolver)
).π¦Response.json()
is a static method for shorthand declaration ofapplication/json
responses on the web!
Now, whenever my test does the matching request, MSW will intercept it and respond to it using the mocked JSON response I've defined. In fact, let's verify that! Let's print whichever result is returned from the
getAuthToken()
function to the console.import { getAuthToken } from './get-auth-token.js'
test('returns the authentication token on successful authentication', async () => {
const result = await getAuthToken({
email: 'kody@epicweb.dev',
password: 'supersecret123',
})
console.log(result)
})
$ npm test
stdout | get-auth-token.test.ts > returns the authentication token on successful authentication
{ token: 'abc-123' }
β get-auth-token.test.ts (1)
β returns the authentication token on successful authentication
π Yoo-hoo!
But let's not get too happy too soon. Vitest may report the test as passing but that's only because it has no assertions. The test doesn't validate anything and so it will always pass.
To complete this test, I will add an assertion for the
token
value returned from the getAuthToken()
function to be the exact value I've provided in the mocked response:import { getAuthToken } from './get-auth-token.js'
test('returns the authentication token on successful authentication', async () => {
await expect(
getAuthToken({
email: 'kody@epicweb.dev',
password: 'supersecret123',
}),
).resolves.toEqual({ token: 'abc-123' })
})
Notice that I've rewritten the entire test to pass the pending promise ofgetAuthToken()
toexpect()
, awaiting the assertion itself. By doing so, I'm creating a nicer experience for when this test fails. Theawait expect().resolves
chaining will print a friendly error message in casegetAuthToken()
rejects, instead of treating it as an unhandled exception in test.Remember that we write tests to fail, and it matters greatly when and how they fail.