I am trying to test an Express API POST Route that uses Express Validator for check
:
usersRouter.post( '/', [ check('name', 'Please enter a name.').not().isEmpty(), check('email', 'Please enter a valid email.').isEmail(), check( 'password', 'Please enter a password of 6 characters or more.' ).isLength({ min: 6 }), ], async (req, res) => { const errors = validationResult(req); if (!errors.isEmpty()) { console.log('errors: ', errors); return res.status(400).json({ errors: errors.array() }); } const { name, email, password } = req.body; try { //... } catch { //... } } );
This API route expects to receive a request consisting of a body that contains the fields, name
, email
, and password
:
const { name, email, password } = req.body
In order to test this route, I have a test file using supertest
and jest
:
const mongoose = require('mongoose'); const supertest = require('supertest'); const app = require('../app'); const testApi = supertest(app); const User = require('../models/User'); test('a token is returned', async () => { // Create a new test user for the HTTP request. const newTestUser = { name: 'bob', email: 'test@test.com', password: 'newtestpw', }; const { name, email, password } = newTestUser; const body = await JSON.stringify({ name, email, password }); // Execute the test. const config = { headers: { 'Content-Type': 'application/json', }, }; let result = await testApi.post('/api/users', body, config); expect(result.status).toBe(200); expect(result.headers).toHaveProperty('token'); }); afterAll(async () => { await mongoose.connection.close(); });
When I execute this test, each check
in the POST API route fails. The following errors
is returned:
errors: Result { formatter: [Function: formatter], errors: [ { value: undefined, msg: 'Please enter a name.', param: 'name', location: 'body' }, { value: undefined, msg: 'Please enter a valid email.', param: 'email', location: 'body' }, { value: undefined, msg: 'Please enter a password of 6 characters or more.', param: 'password', location: 'body' } ] }
Why is the API route not receiving the request I’m sending using Supertest?
Advertisement
Answer
Well, it seems that you’re not sending your values right.
Look closely at where you send your name, email and password, and how you send them. You can try going to your route and console.log the values it’s getting.
And look in how the api.post
function actually works. I suggest looking on the Supertest github page and Superagent docs
Just in case you want to try to solve the problem on your own, I hid the solution in the spoiler. But in short, first:
You don’t need to stringify your body. You should send it as a usual JavaScript object. Also, you don’t need to await the JSON.stringify, as it doesn’t return a promise, it’s synchronous
Second:
The
api.post
function only takes the URL as its argument. To send any data you want along with the request you need to chain.send(data)
after the.post
Third:
The headers are also set by chaining the
.set('Header', 'value')
method before or after the.send
So in the end, your request should look something like this.
testApi .post(url) .set('Content-Type', 'application/json') .send(newTestUser)