Ketika kita akan membuat aplikasi, maka kita perlu untuk mengujinya sebelum dipublish. Pada tutorial ini kita akan menggunakan framework Mocha Chai untuk melakukan pengujian pada aplikasi Book yang akan kita buat dengan menggunakan nodejs.
Apa itu Mocha ?
Mocha merupakan framework yang digunakan pada sisi server maupun client dan dapat membantu kita dalam menulis dan menjalankan pengujian termasuk pengujian unit, integrasi, dan pengujian fungsional.
Mocha menawarkan sintaks yang sederhana dan mudah dipahami. Terdapat juga beberapa fitur seperti pengujian async/await, promise, dan juga callback.
Apa itu Chai ?
Chai merupakan framework pengujian assertion yang komprehensif dan ekspresif. Chai dapat membantu kita agar kode pengujian dapat lebih mudah dibaca dan dipahami.
Chai menyediakan berbagai metode asertif yaitu untuk memeriksa nila, keberadaan, tipe data, dan lain sebagainya. Kita dapat menggunakan Chai bersama Mocha (atau framework pengujian lainnya) untuk membuat pengujian yang ekspresif.
Setup Project
Langkah awal silahkan kalian buat terlebih dahulu folder untuk projectnya. kalian bisa gunakan perintah berikut di terminal untuk membuat folder.
mkdir testing-nodejs
Kemudian silahkan masuk ke dalam folder yang telah dibuat dengan perintah berikut.
cd testing-nodejs
Kemudian silahkan jalankan perintah berikut ini.
npm init -y
Silahkan buka file package.json kemudian tambahkan kode beriut ini.
// ... "scripts": { "start": "node app.js" "test": "mocha tests/*.js --exit" }, // ...
Setelah itu kita akan menginstall beberapa library yang akan kita gunakan.
npm install express mongoose config body-parser
npm install mocha chai --save-dev
Setelah berhasil menginstall library yang dibutuhkan, silahkan kalian buat database di mongodb dengan nama book.
Sekarang silahkan kalian buat file dengan nama app.js di dalam folder kalian. Dan tambahkan kode berikut ini.
const express = require("express"); const app = express(); const mongoose = require("mongoose"); const bodyParser = require("body-parser"); const book = require("./routes/book"); const config = require("config");
kode diatas untuk memanggil library yang sebelumnya telah kita install. Silahkan kalian buat folder config dan buat file default.json didalam folder config yang baru dibuat.
{ "PORT": "4000", "DBHost": "mongodb://127.0.0.1:27017/book" }
Kemduian kita tambahkan kode berikut untuk melakukan koneksi kedalam database dan inisialisasi aplikasi.
//DB Connection mongoose.connect(config.DBHost); const db = mongoose.connection; db.on("error", console.error.bind(console, "connection error:")); // Server Connection app.listen(config.PORT, () => { console.log(`App running on port ${config.PORT}`); }); // Parse application/json app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: true })); app.use(bodyParser.text()); app.use(bodyParser.json({ type: "application/json" })); app.get("/", (req, res) => res.json({ message: "Welcome!" })); module.exports = app;
Silahkan ketik npm start di terminal kalian dan aplikasi akan berjalan di port 4000.
Buat Aplikasi Book
Langkah selanjutnya kita akan membuat route. silahkan kalian buka kembali file app.js kemudian tambahan kode berikut ini.
// ... app.route("/book").get(book.getBooks).post(book.postBook); app .route("/book/:id") .get(book.getBook) .delete(book.deleteBook) .put(book.updateBook); module.exports = app;
Okee, kita telah mempunyai route book dengan method GET,POST,PUT,DELETE. Selanjutnya kita akan membuat sebuah logika di dalam route tersebut supaya dapat menampilkan, membuat, mengedit, dan menghapus book didalam database.
Mari kita buka folder routes dan silahkan buat file book.js di dalam folder routes yang sudah dibuat. Kemudian tambahkan kode berikut.
const mongoose = require("mongoose"); const Book = require("../models/book"); /* * GET /book route to retrieve all the books. */ const getBooks = async (req, res) => { const books = await Book.find(); res.json(books); }; /* * POST /book to save a new book. */ const postBook = async (req, res) => { try { const book = await Book.create(req.body); res.status(201).json({ message: "Book successfully added!", book }); } catch (error) { res.send(error); } }; /* * GET /book/:id route to retrieve a book given its id. */ const getBook = async (req, res) => { const book = await Book.findById(req.params.id); res.json(book); }; /* * DELETE /book/:id to delete a book given its id. */ const deleteBook = async (req, res) => { const book = await Book.findById(req.params.id); if (book) { await book.deleteOne(); res.json({ message: "Book successfully deleted!" }); } }; /* * PUT /book/:id to updatea a book given its id */ const updateBook = async (req, res) => { const newData = { title: req.body.title, author: req.body.author, }; const book = await Book.findByIdAndUpdate(req.params.id, newData, { new: true, runValidators: true, useFindAndModify: false, }); res.json({ message: "Book updated!" }); }; //export all the functions module.exports = { getBooks, postBook, getBook, deleteBook, updateBook };
Setelah itu kita akan membuat model. Silahkan kalian buat folder dengan nama models dan buat file dengan nama book.js d idalam folder models yang beru dibuat. Kemudian tambahkan kode berikut.
const mongoose = require("mongoose"); const Book = mongoose.Schema( { title: { type: String, required: true }, author: { type: String, required: true }, createdAt: { type: Date, default: Date.now }, }, { versionKey: false, } ); Book.pre("save", (next) => { now = new Date(); if (!this.createdAt) { this.createdAt = now; } next(); }); module.exports = mongoose.model("book", Book);
Buat Pengujian Aplikasi
Langkah selanjutnya kita akan membuat pengujian dengan framework Mocha Chai untuk aplikasi book yang telah kita buat. Silahkan kalian buat folder dengan nama tests dan kemudian buat file dengan nama book.js di dalam folder tests yang baru dibuat dan tambahkan kode berikut ini.
const mongoose = require("mongoose"); const Book = require("../models/book"); const chai = require("chai"); const chaiHttp = require("chai-http"); const server = require("../app"); const should = chai.should(); chai.use(chaiHttp); describe("Books", () => { /* * Test the /GET route */ describe("/GET book", () => { it("it should GET all the books", (done) => { chai .request(server) .get("/book") .end((err, res) => { res.should.have.status(200); res.body.should.be.a("array"); done(); }); }); it("it should not POST a book without author field", (done) => { const book = { title: "The Title", }; chai .request(server) .post("/book") .send(book) .end((err, res) => { res.should.have.status(200); res.body.should.be.a("object"); res.body.should.have.property("errors"); res.body.errors.should.have.property("author"); res.body.errors.author.should.have.property("kind").eql("required"); done(); }); }); it("it should POST a book ", (done) => { const book = { title: "The Lord of the Rings", author: "Leravio", }; chai .request(server) .post("/book") .send(book) .end((err, res) => { res.should.have.status(201); res.body.should.be.a("object"); res.body.should.have .property("message") .eql("Book successfully added!"); res.body.book.should.have.property("title"); res.body.book.should.have.property("author"); done(); }); }); }); describe("/GET/:id book", () => { it("it should GET a book by the given id", async () => { const book = new Book({ title: "The Book", author: "Leravio", }); book.save((err, book) => { chai .request(server) .get("/book/" + book.id) .send(book) .end((err, res) => { res.should.have.status(200); res.body.should.be.a("object"); res.body.should.have.property("title"); res.body.should.have.property("author"); res.body.should.have.property("_id").eql(id); }); }); }); }); describe("/PUT/:id book", () => { it("it should UPDATE a book given the id", async () => { const book = new Book({ title: "The Book", author: "Leravio", }); book.save((err, book) => { chai .request(server) .put("/book/" + book.id) .send({ title: "edit", author: "edit", }) .end((err, res) => { res.should.have.status(200); res.body.should.have.property("message").eql("Book updated!"); }); }); }); }); describe("/DELETE/:id book", () => { it("it should DELETE a book given the id", async () => { const book = new Book({ title: "The Book", author: "Leravio", }); book.save((err, book) => { chai .request(server) .delete("/book/" + book.id) .end((err, res) => { res.should.have.status(200); res.body.should.have .property("message") .eql("Book successfully deleted!"); }); }); }); }); });
Penjelasan kode diatas:
- Pada setiap blok describe digunakan untuk mengelompokkan pengujian ke dalam blok-blok yang terorganisir.
- blok it pertama merupakan test untuk menguji endpoint (‘/book’) method GET dengan tujuan untuk mendapatkan semua data book. response harus menghasilkan status code 200 dan return harus berupa array.
- blok it kedua merupakan test untuk menguji endpoint (‘/book’) method POST dengan tujuan untuk menyimpan data book. response harus menghasilkan return errors di karenakan tidak memiliki properti author.
- blok it ketiga merupakan test untuk menguji endpoint (‘/book’) method POST dengan tujuan untuk menyimpan data book. response harus menghasilkan status code 200, return harus berupa object, harus menghasilkan messaage, dan juga harus mempunyai properti judul dan author.
- blok it keempat merupakan test untuk menguji endpoint (‘/book:/id’) method GET dengan tujuan untuk mendapatkan detail data book. response harus menghasilkan status code 200, return harus berupa object, dan juga harus mempunyai properti judul, author, dan id.
- blok it kelima merupakan test untuk menguji endpoint put(‘/book/:id’) method PUT dengan tujuan untuk mengubah data book. response harus menghasilkan status code 200, harus menghasilkan messaage.
- blok it kelima merupakan test untuk menguji endpoint delete(‘/book/:id’) method DELETE dengan tujuan untuk menghapus data book. response harus menghasilkan status code 200, harus menghasilkan messaage.
Untuk menjalankan pengujian kalian bisa menggunakan perintah berikut.
npm test