In my application, I have a middleware to check for a token in a req
in order to access private routes:
const config = require('../utils/config');
const jwt = require('jsonwebtoken');
module.exports = function (req, res, next) {
let token = req.header('x-auth-token');
if (!token) {
return res.status(401).json({ msg: 'No token. Authorization DENIED.' });
}
try {
let decoded = jwt.verify(token, config.JWTSECRET);
req.user = decoded.user;
next();
} catch (err) {
return res.status(401).json({ msg: 'Token is invalid.' });
}
};
In order to send a req
with the correct token in my program's Redux actions, I call the following function, setAuthToken(), to set the auth token:
import axios from 'axios';
const setAuthToken = token => {
if (token) {
axios.defaults.headersmon['x-auth-token'] = token;
} else {
delete axios.defaults.headersmon['x-auth-token'];
}
};
export default setAuthToken;
My Redux action using axios and the setAuthToken() function:
export const addPost = (formData) => async (dispatch) => {
try {
//set the token as the header to gain access to the protected route POST /api/posts
if (localStorage.token) {
setAuthToken(localStorage.token);
}
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const res = await axios.post('/api/posts', formData, config);
// ...
} catch (err) {
// ...
}
};
How can I write a test to test setAuthToken()? The following is my attempt:
import axios from 'axios';
import setAuthToken from '../../src/utils/setAuthToken';
describe('setAuthToken utility function.', () => {
test('Sets the axios header, x-auth-token, with a token.', () => {
let token = 'test token';
setAuthToken(token);
expect(axios.defaults.headersmon['x-auth-token']).toBe('test token');
});
});
The following is the error I get:
TypeError: Cannot read property 'headers' of undefined
Looking up this error, it sounds like it is because there is no req
in my test. If that is the case, how can I re-write my test to send a req
? If not, what am I doing wrong?
In my application, I have a middleware to check for a token in a req
in order to access private routes:
const config = require('../utils/config');
const jwt = require('jsonwebtoken');
module.exports = function (req, res, next) {
let token = req.header('x-auth-token');
if (!token) {
return res.status(401).json({ msg: 'No token. Authorization DENIED.' });
}
try {
let decoded = jwt.verify(token, config.JWTSECRET);
req.user = decoded.user;
next();
} catch (err) {
return res.status(401).json({ msg: 'Token is invalid.' });
}
};
In order to send a req
with the correct token in my program's Redux actions, I call the following function, setAuthToken(), to set the auth token:
import axios from 'axios';
const setAuthToken = token => {
if (token) {
axios.defaults.headers.mon['x-auth-token'] = token;
} else {
delete axios.defaults.headers.mon['x-auth-token'];
}
};
export default setAuthToken;
My Redux action using axios and the setAuthToken() function:
export const addPost = (formData) => async (dispatch) => {
try {
//set the token as the header to gain access to the protected route POST /api/posts
if (localStorage.token) {
setAuthToken(localStorage.token);
}
const config = {
headers: {
'Content-Type': 'application/json',
},
};
const res = await axios.post('/api/posts', formData, config);
// ...
} catch (err) {
// ...
}
};
How can I write a test to test setAuthToken()? The following is my attempt:
import axios from 'axios';
import setAuthToken from '../../src/utils/setAuthToken';
describe('setAuthToken utility function.', () => {
test('Sets the axios header, x-auth-token, with a token.', () => {
let token = 'test token';
setAuthToken(token);
expect(axios.defaults.headers.mon['x-auth-token']).toBe('test token');
});
});
The following is the error I get:
TypeError: Cannot read property 'headers' of undefined
Looking up this error, it sounds like it is because there is no req
in my test. If that is the case, how can I re-write my test to send a req
? If not, what am I doing wrong?
-
Use
console.log(axios)
in your test file to check if it is being mocked? – Lin Du Commented Oct 28, 2020 at 3:31
1 Answer
Reset to default 5Here is my case, there is a __mocks__
directory in my project. There is a mocked axios
. More info about __mocks__
directory, see Manual mock
__mocks__/axios.ts
:
const axiosMocked = {
get: jest.fn()
};
export default axiosMocked;
When I run the test you provide, got the same error as yours. Because mocked axios
object has no defaults
property. That's why you got the error.
import axios from 'axios';
import setAuthToken from './setAuthToken';
jest.unmock('axios');
describe('setAuthToken utility function.', () => {
test('Sets the axios header, x-auth-token, with a token.', () => {
let token = 'test token';
setAuthToken(token);
expect(axios.defaults.headers.mon['x-auth-token']).toBe('test token');
});
});
So I use jest.unmock(moduleName) to use the real axios
module instead of the mocked one.
After that, it works fine. Unit test result:
PASS src/stackoverflow/64564148/setAuthToken.test.ts (10.913s)
setAuthToken utility function.
✓ Sets the axios header, x-auth-token, with a token. (5ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
Snapshots: 0 total
Time: 13.828s
Another possible reason is you enable automock. Check both mand and jest.config.js
file.