Learning to build as well as test NodeJS RESTful API using Mongoose ORM
- Use of different enviornments -> Local and Heroku
- Use of local MongoDB for local enviornment and use of mlab for Heroku
- Deployed on HEROKU -> https://secret-wildwood-28396.herokuapp.com/todos This URI makes GET request
- npm library which helps to structure the data
- http://mongoosejs.com/
Setting up mongoose
npm install [email protected] --save
- Setting up mongoose in NodeJs application
-
All the server-side logic will reside inside Server folder in Server.js
-
Server.js is the root of the application
-
In Server.js,
- Establish connection to MongoDB database using mongoose ORM.
- Create model for everything you want to store to the database
// Creating a Todo Model using mongoose var Todo = mongoose.model('Todo', { text: { type: String }, completed: { type: Boolean }, completedAt: { type: Number } });
-
Hence, Todo model has properties => text of type String, completed of type Boolean, completedAt of type Number
-
Create an instance of model
var newTodo = new Todo({ text: 'Pay internet bill' });
-
Save that instance to MongoDB database
newTodo.save().then((doc) => { console.log('Saved todo', doc); }, (e) => { console.log('Unable to save Todo'); });
- Improving Mongoose models
-
Adding validations, setting some properties as required, setting defaults values
-
For example, we should not add a todo if the object doesn't have text or completed property (in the context of Todo application),because if we try to create an object without these properties then a document entry is still made in MongoDB with no entry for text and completed and this should not happen
var todo = new Todo({ });
-
Should provide smart default value to Completed property (Like nobody is going to create a todo if they have already completed it. Hence completed should be set to false by default)
Hence better todo mongoose model is
var Todo = mongoose.model('Todo', {
text: {
type: String,
required: true, // validator required (Value must exist)
minlength: 1, // Custom validator for Strings
trim: true //trims off any white space at the end or begining of the string
},
completed: {
type: Boolean,
default: false
},
completedAt: {
type: Number,
default: null // completedAt will be present only when todo is been completed
}
});
-
Installing Postman (Important tool to test REST API)
- Installing a tool - Postman, to test HTTP requests
- https://www.getpostman.com/apps
-
Refactoring code
- Database configuration is placed in separate file
- Models are placed in different file
- Hence, in server.js, only express route handlers are kept. Hence, server.js will be only responsible for the routes
-
Creating HTTP Routes
-
Install express and body-parser
npm install express body-parser --save
body-parser
- essentially parses the body -> takes string object and converts into JavaScript object
- lets us send JSON to server. Server then can take JSON and do something with it.
-
Resource creation Endpoint - POST /todos
- This endpoint will be used to add new to-dos
- Inside Postman, make POST request to /todos by entering some text and setting the type of raw text inside body to JSON
- Run your server.js file Following response we get, when we try to make POST request through POSTMAN
At the same time, on console you can check the response
- Testing in the POSTMAN, if "text" contains empty string, i.e. if user tries to create a to-do with empty string, then server returns error in body along with 400 status code
-
Testing POST /todos
- Writing test-cases for /todo
- Verify that when we send correct data as a body, we get 200 status code with document including id
- When we send bad data, expect back 400 with error object
- Install expect for assertions, mocha for entire test suite, supertests to test express routes as dev-dependencies
npm install expect mocha supertest --save-dev
- In order to run the tests from terminal, make few changes in the package.json
"scripts": { "test": "mocha server/**/*.test.js" }
- Running the tests
npm run test
- Writing test-cases for /todo
-
List resources Endpoint - GET /todos
- This route will be used to get the information about available to-dos
-
Getting individual resource Endpoint - GET /todos/:id
-
This API route will be used to fetch an individual todo
Case where object id is valid and is present in the MongoDB collection, then the response will have body and status code of 200
Case where object id is valid but not in the MongoDB collection, then the response will have empty body with status code of 404. For the following case, I have tweaked the last digit of object id -
Testing GET /todos/:id
- 3 test cases to test the route /todos/:id
- One that fetches individual to-do item and verifies when we pass valid object id and that id matches a document, then that document actually comes back in the response body
- Another that makes sure that when we pass invalid object id, 404 is returned
- Another test case that verifies when we pass valid object id but does not match a document, 404 is returned
- 3 test cases to test the route /todos/:id
-
-
Delete a resource Endpoint - DELETE /todos/:id
-
This route will be responsoible for deleting a to-do by its id
-
remove() -> Removes multiple records matching the query
-
findOneAndRemove() -> Removes a document by matching id
-
findByIdAndRemove() -> Removes a document by matching id
run server.js and make a DELETE request from postman
From above image, it is evident that, the document got deleted.
Checking the all the dcouments in MongoDB,
-
-
Testing DELETE /todos/:id
- Test case to verify that when we pass in an ID that does exist in the todo collection, gets removed
- If not found return 404. (If you are trying to delete an item that is not in the databse)
- Should return 404 if object ID is invalid i.e. when we have invalid object id and try to delete it, we should get back 404 status code
-
Update a resource Endpoint - PATCH /todos/:id
Lodash provides utility functions
npm install lodash --save
Out of 2 todos, we will try to update a todo with id 5ab58f9d14f0001bb0c9d491 and change the text property as well as completed property
In MongoDB, we can see the updated value of the document -
Testing PATCH /todos - COMPLETED TO-DO -> Test case to verify if the text property is changed, completed is true and completedAt is number - NOT COMPLETED TO-DO -> Test case to verify if the text property is changed, completed is false and completedAt is null