Testing the Middleware
Recall how the user registration endpoint did not have any middleware. For the purposes of demonstrating how to test a middleware, we'll just be grabbing the isAuthenticated
middleware that we created and test that instead.
File: src/middleware/auth.middleware.js
const globalResponseDto = require('../responses/globalResponseDto')
const isAuthenticated = (req, res, next) => {
if (!req.session.user) {
return res.status(401).json(
globalResponseDto({
status: 'error',
code: 401,
message:
'Access denied: you must be logged in to access this API endpoint.',
data: null,
errors: ['You must be logged in.']
})
)
}
next()
}
module.exports = isAuthenticated
Testing the middleware is a lot trickier than just a regular function. This reason why is because we are expected to stick to a particular function signature (req, res, next)
.
The answer to this is to mock out those particular parameters. The way to do it is to use jest.fn
, which we will use to help us write out helpers like mockRequest
, mockResponse
, and mockNext
functions.
File: src/middleware/__tests__/auth.middleware.test.js
const isAuthenticated = require('../auth.middleware')
const globalResponseDto = require('../../responses/globalResponseDto')
const mockRequest = (userData) => ({
session: {
user: userData
}
})
const mockResponse = () => {
const res = {}
res.status = jest.fn().mockReturnValue(res)
res.json = jest.fn().mockReturnValue(res)
return res
}
const mockNext = () => {
return jest.fn()
}
describe('Test Suite: isAuthenticated middleware', () => {
// our tests go here...
})
The Passing Test
Now watch as we pass the mockRequest
, mockResponse
, and mockNext
functions into our isAuthenticated
function. If everything goes well, then we should expect the next
to be invoked.
test('Access granted, next() should be invoked in express', async () => {
// 1. Arrange
const req = mockRequest({ first_name: 'john' })
const res = mockResponse()
const next = mockNext()
// 2. Act
await isAuthenticated(req, res, next)
// 3. Assert
expect(next).toHaveBeenCalled()
})
The Passing Test
Now for the failing test, we should expect the correct status code and output.
test('Access denied, respond with a status 401', async () => {
// 1. Arrange
const req = mockRequest()
const res = mockResponse()
// 2. Act
await isAuthenticated(req, res)
// 3. Assert
expect(res.status).toHaveBeenCalledWith(401)
expect(res.json).toHaveBeenCalledWith(
globalResponseDto({
status: 'error',
code: 401,
message:
'Access denied: you must be logged in to access this API endpoint.',
data: null,
errors: ['You must be logged in.']
})
)
})
Last updated