I have a controller that registers a user, however, testing it does not work. I am using Jest in Node version 16. Here is the controller: I get the following error TypeError: response.status(...).json is not a function
I did implement the json method of the object so I don't know why I'm getting this error
class AuthenticationController {
registerNewUser = async(request:Request, response:Response, next:NextFunction) =>{
const username = request.body.username
const password = request.body.password
if(!username || !password){
response.status(400).json({success:false, 'no username or password'})
}
const query = {username: username}
const user = await User.findOne(query)
if(user){
response.status(400).json({message: 'User exists'})
}
const hashUtility = new HashUtil()
const {hash} = hashUtility.createHash(password)
const createQuery = (username: username,hash:hash)
await User.create( createQuery)
// TypeError: response.status(...).json is not a function
// is now thrown here
response.status(200).json(createQuery)
}
}
export {AuthenticationController}
Here is my test class
describe('UserAuthController test suite', ()=>{
let authController:AuthenticationController
beforeEach(()=>{
authController = new AuthenticationController()
})
it('should successfully register a new user ', async ()=>{
let user = new User({
username: 'user@gmail.com',
hash: 'ddh44500000',
})
let mockRequest = {
body: {
username: 'user@gmail.com',
password: 'mypassword'
}
}
let responseObject = {};
let mockResponse: Partial<Response> = {
statusCode: 200,
status: jest.fn().mockImplementation(()=>200),
json: jest.fn().mockImplementation((result) =>{
responseObject = result
})
}
UserConfig.findOne =
jest.fn().mockImplementation((query)=>{
return null
})
let next = jest.fn()
let hashUtility = new HashUtil()
jest.spyOn(hashUtility, 'createHash').mockImplementationOnce((password) =>{
return {hash: 'ddh44500000'}
})
await authController.registerNewUser(mockRequest as Request, mockResponse as
Response, next)
console.log(`ResponseObjeect ${responseObject}`)
})
})
I don't know what I'm missing in my test code. Please help
The problem is that you're not creating your mockResponse
object properly.
You're response object's methods should support method chaining as described in your code:
response.status(200).json({ message: "msg" });
In order to be able to call .json({ message: "msg" })
the previous status
method must return this
(the response
object).
But in you're test code you've the following:
let mockResponse: Partial<Response> = {
statusCode: 200,
status: jest.fn().mockImplementation(() => 200),
json: jest.fn().mockImplementation((result) => {
responseObject = result;
}),
};
So, when you pass this mock response object to the middle-ware and it calls response.status(400)
it returns 200
(according to your jest.fn().mockImplementation(() => 200)
).
Then it chains the .json({})
call but as the returned value from previous call was 200
, so (200).json({...})
throws an error:
TypeError: response.status(...).json is not a function
This is an easy fix, you just need to return the mockResponse
object from each mock methods, like the following snippet:
let responseObject = {};
let mockResponse = {
statusCode: 200,
status: jest.fn().mockImplementation((status) => mockResponse),
json: jest.fn().mockImplementation((result) => {
responseObject = result;
return mockResponse
}),
};