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 = isAuthenticatedTesting 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