I'm on node.js using Mongoose model and testing with Mocha with Sinon.
The function I'm testing:
exports.findAllUsers = (req, res) => {
UserCollection.find()
.then(users => {
res.status(500)
.send(users)
})
.catch(err => {
res.status(500)
.send({message: err.message || "error occurred retriving users informations"})
})
Here my test code:
describe("findAllUsers", () => {
const sandbox = sinon.createSandbox();
afterEach(function () {
sinon.restore();
sandbox.restore();
});
const req = {
params: {
id: new mongoose.Types.ObjectId(),
},
};
const statusJsonSpy = sinon.spy();
const res = {
send: sinon.spy(),
status: sinon.stub().returns({ json: statusJsonSpy }),
};
it("should return all users data if found", async () => {
mongoose.Model.find = sandbox
.stub()
.returns(Promise.resolve("users data"));
await findAllUsers(req, res);
console.log(res.send.callCount);
expect(res.send).to.have.been.calledWith("users data");
});
res.send.callCount return 0, res.send is never been called thus the test fail!
If I edit my function as in the following, the test work:
exports.findAllUsers = (req, res) => {
UserCollection.find()
.then(users => {
res.status(500)
res.send(users) // added res, not using concatenation
})
.catch(err => {
res.status(500)
.send({message: err.message || "error occurred retriving users informations"})
})
}
Related
I'm trying to learn testing with jest and supertest. I have this simple API:
app.get("/", (req, res) => {
res.json({ name: "bob" });
});
app.delete("/delete", async (req, res) => {
const result = await Todos.deleteOne({ _id: req.body.id });
res.send(result);
});
app.post("/add", (req, res) => {
const { item, status } = req.body;
const todo = new Todos({
item,
});
todo.save();
res.send(todo);
});
They all work. I also have these tests **which when individually run they all pass, but when I run them together the delete fails.
My logic is, when adding a post, I'm passing the id of the created post to the test so that the delete test can use
const request = require("supertest");
const app = require("../server");
describe("testing Todos API", () => {
let payload = { id: "6156c95c9ecf28237844489b" };
let item = { item: "test" };
it("get", (done) => {
request(app)
.get("/")
.expect(200)
.end((err, res) => {
expect(res.body).toEqual({ name: "bob" });
expect(res.body.name).toEqual("bob");
done();
});
});
it("post", (done) => {
request(app)
.post("/add")
.send(item)
.expect(200)
.end((err, res) => {
payload.id = res.body._id;
expect(res.body.item).toEqual(item.item);
done();
});
});
it("delete", (done) => {
request(app)
.delete("/delete")
.send(payload)
.end((err, res) => {
console.log(res.body);
expect(res.body.deletedCount).toEqual(1);
done();
});
});
});
But I get the error of error MongoServerError: E11000 duplicate key error collection and deletedCount is 0
I'm trying to test a controller function using jest, and i want to test all three status return
const messagesSender = async (req, res) => {
try {
const { message } = req.body;
if (!message) {
return res.status(400).send({ message: 'Message cannot be null' });
}
return res.status(200).send(message);
} catch (error) {
return res.status(500).json({ error: 'Internal Error' });
}
};
module.exports = { messagesSender };
Test file:
const messages = require('../controller/messagesController');
describe('Testing Messages Controller', () => {
it('should return internal error', async () => {
const req = {
body: {
message: 'testing',
},
};
const res = {
send: jest.fn(),
status: jest.fn(() => res),
};
const messageResponse = await messages.messagesSender(req, res);
messageResponse.mockImplementation(() => {
throw new Error('User not found');
});
expect(res.status).toBeCalledWith(500);
});
});
But i'm receiving the error:
TypeError: Cannot read property 'mockImplementation' of undefined
How can i fix this and test the 500 result?
it('should return internal error', async () => {
const req = {
body: {
message: 'testing',
},
};
const res = {
send: jest.fn().mockImplementation(() => {
throw new Error('User not found');
}),
status: jest.fn(() => res),
};
await messages.messagesSender(req, res);
expect(res.status.mock.calls[1][0]).toBe(500);
});
In your case send function returning nothing and causing this problem. In this case status method have been called twice, so you need to check the second call.
I'm trying to return a custom message when I do a mongoose.find query and it doesn't find anything on the system.
At the moment I have the following and it works, but I was wondering if there is a better way of accomplishing what I'm doing .
// <status> => one of ["valid", "expired", "attributed"]
const getByStatus = (status) => {
return new Promise((resolve, reject) => {
PhotoCodes.find({ status: status })
.then((response) => {
resolve(response)
})
.catch((error) => {
reject(error)
})
})
}
router.post('/byStatus', (req, res, next) => {
const { status } = req.body
photoCodesModel
.getByStatus(status)
.then((response) => {
if (response.length == 0 ) {
res.status(404).send('Not Found') // [ASK]: If response is an empty "[]" treat it as nothing was found. Is there a better way of doing this?
} else {
res.status(200).json({ result: 'ok', data: response })
}
})
.catch((error) => {
res.status(400).json({ result: 'ok', error: error })
})
})
You can use async/await to do, like this
const getByStatus = async (status) => {
const photo = await PhotoCodes.find({ status: status })
return photo .
}
router.post('/byStatus',async (req, res, next) => {
const status = req.body.status;
try {
const photo = await getByStatus(status)
if(photo.length!==0) {
return res.status(200).json({ result: 'ok', data: photo })
}
return res.status(404).json({message : "treat it as nothing was found"})
}
catch(error) {
return res.status(400).json({ result: 'ok', error: error })
}
});
product-operations.component.ts
deleteProduct() {
this.productsService.delete_product(this.deleteID).subscribe((res: any) => {
console.log("helloooooo");
});
};
product.service.ts
delete_product(id) {
return this.http.delete("http://localhost:3000/delete_product/" + id);
}
backend
exports.deleteProduct = (req, res, next) => {
const id = req.param("id");
Product.deleteOne({ _id: id })
.then(() => {
console.log("deleted");
})
.catch(err => {
console.log(err);
});
};
Problem:
In the above codes, the deleteProduct function in product-operations.component.ts doesn't work properly. More precisely, it does the removal. But after doing the uninstall, subscribe doesn't run its contents. This prevents my instant update after deletion. How can I solve this?
Try to send a response back from the server.
exports.deleteProduct = (req, res, next) => {
const id = req.param("id");
Product.deleteOne({ _id: id })
.then(() => {
res.send({}) // or res.send({id: id})
console.log("deleted");
})
.catch(err => {
res.status(500)
res.send({error: err})
console.log(err);
});
};
I have created the backend operations using Node.js / MongoDB and created services for them, but when I run the server it indicates that I've connected successfully, but I can't see a database in Robo 3T.
Here is what I coded:
DBConfig.js
var mongoose = require ('mongoose');
var Schema = mongoose.Schema;
var UserSchema = new Schema({
name : {
type : String,
require : true
},
address : {
type : String,
require : true
}
});
mongoose.model("User", UserSchema);
module.exports = mongoose;
mongoose.connect('mongodb://127.0.0.1:27017/TestDB4', function(err){
if(err)
{
console.log(err);
process.exit(-1);
}
console.log("Connected to the db")
});
I can't see an error. Why isn't the DB created?
check your User.Controller.js as this below,
var mongoose = require('../DBSchema/SchemaMapper');
var UserSchema = mongoose.model('User');
var UserController = function(){
this.insert = (data) => {
return new Promise((resolve, reject) => {
var user = new UserSchema({
userName: data.userName,
password: data.password
});
user.save().then(() => {
resolve({status: 200, message: "Added new user"});
}).catch(err => {
reject({status: 500, message: "Error:- "+err});
})
})
}
this.update = (id, data) => {
return new Promise((resolve, reject) => {
UserSchema.update({_id: id}, data).then(() => {
resolve({status: 200, message: "update user"});
}).catch(err => {
reject({status: 500, message: "Error:- " + err});
})
})
}
this.searchAll = () => {
return new Promise((resolve, reject) => {
UserSchema.find().exec().then((data) => {
resolve({status: 200, data: data});
}).catch(err => {
reject({status: 500, message: "Error:- " + err});
})
})
}
this.search = (id) => {
return new Promise((resolve, reject) => {
UserSchema.find({_id:id}).exec().then(user => {
resolve({status: 200, data: user});
}).catch(err => {
reject({status: 500, message: "Error:- " + err});
})
})
}
this.delete = (id) => {
return new Promise((resolve, reject) => {
UserSchema.remove({_id:id}).then(() => {
resolve({status: 200, message: "remove user"});
}).catch(err => {
reject({status: 500, message:"Error:- " + err});
})
})
}
}
module.exports = new UserController();
And User.Route.js as below,
var express = require('express');
var router = express.Router();
var Controller = require('./User.Controller');
router.post('/', (req, res) => {
Controller.insert(req.body).then(data => {
res.status(data.status).send({message: data.message});
}).catch(err => {
res.status(err.status).send({message: err.message});
})
});
router.put('/:id', (req, res) => {
Controller.update(req.params.id, req.body).then(data => {
res.status(data.status).send({message: data.message});
}).catch(err => {
res.status(err.status).send({message: err.message});
})
});
router.get('/', (req, res) => {
Controller.searchAll().then(data => {
res.status(data.status).send({data: data.data});
}).catch(err => {
res.status(err.status).send({message: err.message});
});
});
router.get('/:id', (req, res) => {
Controller.search(req.params.id).then(data => {
res.status(data.status).send({data: data.data});
}).catch(err => {
res.status(err.status).send({message: err.message});
});
});
router.delete('/:id', (req, res) => {
Controller.delete(req.params.id).then(data => {
res.status(data.status).send({message: data.message});
}).catch(err => {
res.status(err.status).send({message: err.message});
})
})
module.exports = router;
check your app.js as follows
const Express = require("express");
const BodyParser = require("body-parser");
const Routes = require("./Routes");
const Cors = require("cors");
const app = Express();
app.use(Cors());
app.use(BodyParser.urlencoded({ extended: false }));
app.use(BodyParser.json());
app.use('/', Routes);
app.listen(8083, 'localhost', (err) => {
if(err) {
console.log(err);
process.exit(-1);
}
console.log("Server listen port 8083");
});
and Routes.js as follows,
var Express = require("express");
var Routes = Express.Router();
var UserRoute = require('./src/User/User.Route');
var CommentRoute = require('./src/Comment/Comment.Route');
Routes.use('/user/', UserRoute);
Routes.use('/comment/', CommentRoute);
module.exports = Routes;