I am testing an express API with supertest. I am trying to pass in body parameters into the test, as can be seen in the code snippets below, but it appears that the body parameters don't get passed in correctly since I get an error message that the body parameters are undefined.
Running the test with command mocha --recursive returns the following error:
Cannot read property 'email' of undefined
Below is the code from file email-suite.js referencing supertest
'use strict';
var express = require("express");
var bodyParser = require('body-parser');
var mongoose = require("mongoose");
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
var supertest = require("supertest");
var chai = require("chai");
var should = chai.should();
var api = require("../server.js");
describe("Email Module", function() {
this.timeout(25000);
before(function(done){
mongoose.createConnection(/* connectionstring */);
mongoose.connection.on('open', function(err) {
if(err) console.log(err);
console.log('connected to server');
});
done();
});
it("Check Email Count", function(done) {
var body = { email: "email#email.com" };
supertest(api)
.post("/emailCount")
.set('Accept', 'application/json')
.send(body) // body is undefined
.expect(200)
.expect('Content-Type', /json/)
.end(function(err, res) {
if(err) return done(err);
res.body.count.should.equal(2);
done();
});
});
});
Below is the code from file email-api.js
'use strict';
var express = require("express");
var bodyParser = require('body-parser');
var router = express.Router();
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
router.post('/emailCount', function(req, res) {
var email = req.body.email; // req.body is undefined
}
module.exports = router;
Below is the code from the file server.js
var express = require("express");
var app = express();
app.set("port", process.env.PORT || 3000);
var router = require("./user/email-api");
app.use('/', router);
app.listen(app.get("port"), function() {
console.log("App started on port " + app.get("port"));
});
module.exports = app;
Put body-parser always after express object and before every routes in main server file like this
var app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: true}));
//Router task start from here
Other wise always will get undefined since router call first and body parsed later.
Thank you abdulbarik for your answer. I want to add some extra information to aid clarity in case people are still getting undefined values for the request body object, and if (as in my case) your routers and tests are setup differently.
Here is the router that we shall test:
// router.js
const express = require("express");
const router = express.Router();
router.post("/", (req, res) => {
res.json({ success: true, data: req.body });
});
module.exports = router;
The following test code will result in the request body being undefined, and thus the test failing:
// router.test.js
const express = require("express");
const request = require("supertest");
const bodyParser = require("body-parser");
// set up the test app - this will fail
const app = express();
app.use("/routerPath", require("./router")); // this will cause the test to fail, as the router should be setup after the body-paser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// run the test
it("successful response", async () => {
const response = await request(app)
.post("/routerPath")
.send({
firstname: "John",
lastname: "Smith",
})
.set("Accept", "application/json");
expect(response.status).toEqual(200);
expect(response.body).toEqual({
success: true,
data: {
firstname: "John",
lastname: "Smith",
},
});
});
The reason why, as explained by abdulbarik, is that the body-parser code should always be before the router code, so that the parser runs before the router. To make the test pass, simply swap these lines around:
// set up the test app - this will work now
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use("/routerPath", require("./router")); // the router setup should happen after the body-parse setup
I hope that is a helpful clarification.
Related
I'm trying to send a json to my nodeJs app through POST Method in body.
For that I'm using POSTMAN to create the request, with the proper consnt-type header and body JSON Rows. Tho the message back is "OK" in console the req.body is {} empty.
Would you have an idea what's wrong in my code?
const bodyParser = require('body-parser');
const { Client } = require('pg');
const express = require('express');
const app = express();
// create application/json parser
const jsonParser = bodyParser.json()
// create application/x-www-form-urlencoded parser
const urlencodedParser = bodyParser.urlencoded({ extended: false })
const hostname = '127.0.0.1';
const port = 3000;
const dbSchema = 'public';
const client = new Client({
user: 'postgres',
host: 'localhost',
database: 'postgres',
password: '123123',
port: 5432,
});
client.connect();
/* =========== Some Initialize staff =============== */
// parse various different custom JSON types as JSON
app.use(bodyParser.json({ type: 'application/*+json' }))
app.use(bodyParser.urlencoded({
extended: true
}));
app.listen(port, hostname, () => {
console.log(`Server running at http://${hostname}:${port}/`);
});
/* =========== FROM HERE =============== */
app.post('/post-test', urlencodedParser, (req, res) => {
console.log('Got body:', req.body);
res.sendStatus(200);
});
app.get('/',(req,res)=>{
res.status(200).send('Get Ready for something awesome!\n');
});
enter image description here
You should use app.use(bodyParser.json());, in your code const jsonParser = bodyParser.json() this is not used.
Update: Or you can apply jsonParser middleware directly to the post route:
app.post("/post-test", jsonParser, (req, res) => {
console.log("Got body:", req.body);
res.json({ ...req.body });
});
Can't figure what is happening so, I am posting the code that works for me -
let express = require('express');
let app = express();
const authorRoute = express.Router();
authorRoute.use(express.json());
authorRoute.use(express.urlencoded({extended:true}));
authorRoute.post('/post-test', async (req, res) => {//req.body});
app.use(authorRoute);
Also, make sure to test with a well-formed JSON.
version "express": "^4.17.1",
When I wanna make a POST req using Postman where I already set the content-type to application/json and I console.log the req.body.name or sth else it only returns undefined.
Here's the code:
index.js
const app = express();
const mongoose = require("mongoose");
const dotenv = require("dotenv");
const authRoute = require("./routes/auth");
dotenv.config();
mongoose.connect(
process.env.DB_CONNECT,
{ useNewUrlParser: true, useUnifiedTopology: true },
() => console.log("connected to mongoDB")
);
// Middleware
app.use(express.json());
// Routes
app.use("/api/user", authRoute);
// Run Server
const PORT = 5000;
app.listen(PORT, () => console.log(`server running on port ${PORT}`));
auth.js
const router = require("express").Router();
const User = require("../model/User");
router.post("/register", async (req, res) => {
const user = new User({
name: req.body.name,
email: req.body.email,
password: req.body.password,
});
console.log(req.body.name);
});
module.exports = router;
Since you are not using body parser and using only express.json() send requests as raw then pick JSON. The format that you should write looks like this:
{
"name": "Some name",
"lastname": "...."
}
Here is how your postman should look like:
Install Body parser as:
npm install --save body-parser
and then update your index.js file as:
var bodyParser = require('body-parser')
app.use( bodyParser.json() ); // to support JSON-encoded bodies
app.use(bodyParser.urlencoded({ // to support URL-encoded bodies
extended: true
}));
just add these line after
// Middleware
app.use(express.json());
for example
// Middleware
app.use(express.json());
app.use(express.urlencoded{extended: true})
This express setting will allow you to parse html-body
Getting a 404 error on my POST route, here is what I have done in my auth.js (routes) file:
const express = require('express');
const router = express.Router();
const connection = require('../../helpers/db.js');
const bodyParser = require("body-parser");
router.use(bodyParser.json());
router.use(bodyParser.urlencoded({
extended: true
}));
//create a new user
router.post('/signup', function (req, res) {
const insert = `INSERT INTO users ( email, password, name, lastname) values ('${req.body.email}', '${req.body.password}','${req.body.name}', '${req.body.lastname}' )`
connection.query(insert, function (err, result) {
if(err) {
console.log('mysql error', error);
res.status(500);
res.send(error);
} else {
console.log('a new user was added!');
res.send('Congrats, new user!');
}
})
});
module.exports = router;
Here is my app.js file:
const http = require("http");
const path = require("path");
const express = require("express");
const bodyParser = require("body-parser");
const morgan = require("morgan");
const app = express();
const authRouter = require("./routes/auth/auth");
// Configuring the app
app.use(morgan("dev"));
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
app.use(express.static(__dirname + "/public"));
app.use("/signup", authRouter);
//starting node server
const server = app.listen(process.env.PORT || 3001, function(err) {
if(err) throw err;
console.log("Listening on port " + server.address().port);
});
If I change my route into a GET, it works fine, but as soon as I do a POST route it would keep telling me on postman there is a 404 error, been trying many things but im now stuck! Im a beginner here :)
I think you added a prefix to your route so the route is /signup/signup
Try to change this
app.use("/signup", authRouter);
To this
app.use(authRouter);
Like i said in title. req.body don't work. I saw some examples and that use req.body(body-parser) well. But in my code, req.body is keep undefined. Also i found same problems and they said "app.use(bodyParser.json())" will work. But for me, no. So i ask how can i solve this error. Plz, help me.
This code is simple, Express and Vue login, signin test project. I think problem is in server file.
Server
var express = require("express");
var bodyParser = require("body-parser");
var path = require("path");
const mongoose = require("mongoose");
var index = require("./routes/index.js");
var login = require("./routes/login.js");
var signin = require("./routes/signin.js");
var app = express();
var http = require("http").Server(app);
mongoose.connect("mongodb://localhost:27017/test");
app.use('/', index);
app.use('/api/login', login);
app.use('/api/signin', signin);
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.set("port", process.env.PORT || 3000);
app.use(express.static(path.join(__dirname, 'public')));
http.listen(app.get("port"), function() {
console.log("server start in " + app.get("port"));
})
Router
const express = require("express");
const router = express.Router();
const User = require("../models/user.js");
router.post("/", function(req, res, next) {
const id = req.body.id;
const password = req.body.password;
let info = {
error: "false",
words: "",
id: "",
password: ""
}
User.findOne({ id: id }, function(err, user) {
if(err) {
info.error = "true";
info.words = "Unknown Error Come Out.";
return res.send(info);
}
if(!user) {
info.error = "true";
info.words = "Please Check Your ID or Password";
return res.send(info);
}
info.id = id;
info.password = password;
console.log(info);
return res.send(info);
})
});
module.exports = router;
This body can not be resolved because of your middleware declaration order. You can check from the following blog about middleware execution sequence. Basically it equals to middleware declaration order.
https://derickbailey.com/2016/05/09/in-what-order-does-my-express-js-middleware-execute/
Declare bodyParser middleware before router middleware can solve your problem
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use('/api/login', login);
I built an app using node.js + expressjs and am using mocha to test my post request. My test is failing because the response from my post request is null but I don't know why...
My API:
api.post('/api/addreport', function(req, res) {
console.log('add report hit..'); //this does not print during testing
console.log(req.body); //this does not print during testing
res.sendStatus(200);
});
My test:
var express = require('express');
var app = express();
var chai = require('chai');
var expect = require('chai').expect;
var should = require('should');
var supertest = require('supertest');
var server = supertest.agent("https://localhost:3001");
var request = require('supertest');
var bodyParser = require('body-parser');
//Body parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
it("should post", function(done){
request(app.listen())
.post('/api/addreport/')
.send(data)
.end(function(res){
console.log('---response---');
console.log(res); //returns null
expect(res.status).to.equal(200); //returns status of null
done();
})
});
running mocha ajax results in:
1) should post:
Uncaught TypeError: Cannot read property 'status' of null
My data:
var data = {
report_id: 'abc123' + Math.random(10),
project_code: 'test_project_code',
startDate: '2016-01-01',
endDate: '2016-01-15',
};
Can someone help?
Thanks in advance!
If you are using supertest it doesn't require that you start your app in any port. Just add app.listen at supertest request
var express = require('express');
var app = express();
var chai = require('chai');
var expect = require('chai').expect;
var should = require('should');
var supertest = require('supertest');
var server = supertest.agent("https://localhost:3001");
var request = require('supertest');
var bodyParser = require('body-parser');
//Body parser
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
it("should add report", function(done){
request(app.listen()) // change here
.post('/api/addreport/')
.send(data)
.expect(200)
.end(function(err,res){
done();
});
});