npm i -D jest
.
├── node_modules
├── src
│ ├── controllers
│ ├── models
│ │ └── data-source.js (Connect to DB using TypeORM)
│ ├── routes
│ ├── services
│ └── utils
├── tests
│ └── **user.test.js**
├── .env
├── **.env.test**
├── .gitignore
├── **app.js**
├── package-lock.json
├── package.json
└── **server.js**
router
, middleware
code of applicationcreateApp
function that returns app
const express = require("express");
const cors = require("cors");
const morgan = require("morgan");
const dotenv = require("dotenv");
dotenv.config();
const routes = require("./src/routes");
const { errorHandler } = require("./src/utils/errorHandling.js");
const createApp = () => {
const app = express();
app.use(express.json());
app.use(cors());
app.use(morgan("combined"));
app.use(routes);
app.use(errorHandler);
return app;
};
module.exports = { createApp };
createApp
function to use app
that created in app.js
startServer
function that includes AppDataSource.initialize()
and app.listen()
.server.js
when start server, and use app
(= return value ofcreateApp
) in test code.require("dotenv").config();
const { createApp } = require("./app");
const { AppDataSource } = require("./src/models/data-source");
const startServer = async () => {
const app = createApp();
// Connect to DB & initialize
await AppDataSource.initialize();
const PORT = process.env.PORT;
app.listen(PORT, () => {
console.log(`Listening on Port ${PORT}`);
});
};
startServer();
describe
but also test
are consists of (description
, callback
)description
: Category or description about the logicdescribe
and test
can be declaired in callback
callback
and we can compare the values with expect
to see if they were performed well.describe
can helps adding caption about testjest
instruction.test.js
, .spec.js
// npm i --save-dev supertest
// Send a test request to the app using the request of the *supertest*.
const request = require("supertest");
// Call CreateApp function to use app in request of supertest.
const { createApp } = require("../app");
// Call DataSource object for connecting to DB
const { AppDataSource } = require("../src/models/data-source");
// Category
describe("Sign Up", () => {
let app;
// Before start the test, create app object
beforeAll(async () => {
app = createApp();
// We can initialize DB here, but I moved the code to server.js to avoid some log :
// Jest has detected the following 1 open handle potentially keeping Jest from exiting:
//● TCPWRAP
// ...
// await AppDataSource.initialize();
});
afterAll(async () => {
// Remove all unnecessary data in test DB
// If TRUNCATE instruction doesn`t work because of foreign key,
// temporarily release the foreign key and restore.
await AppDataSource.query(`SET foreign_key_checks = 0;`);
await AppDataSource.query(`TRUNCATE users`);
await AppDataSource.query(`SET foreign_key_checks = 1;`);
// After all tests are finished, disconnect DB
await AppDataSource.destroy();
});
// Test all different cases.
// It helps to check if the code is well develpted for your intentions from the test stage!
// 1. Check the emaill address rule
test("FAILED: invalid email", async () => {
// Send test request to app using supertest의 request
await request(app)
.post("/users/signup") // HTTP Method, Endpoint address
// body
.send({
email: "wrongEmail",
password: "password001@",
username: "testName",
mobile: "testMobile",
})
.expect(400) // Test appropriate statusCode and response using expect()
.expect({ message: "invalid email!" });
});
// 2. Check creating user
test("SUCCESS: created user", async () => {
await request(app)
.post("/users/signup")
.send({
email: "wecode002@gmail.com",
password: "password001@",
username: "testName",
mobile: "testMobile",
})
.expect(201);
});
// 3. Check duplicated email
test("FAILED: duplicated email", async () => {
await request(app)
.post("/users/signup")
.send({
email: "wecode002@gmail.com",
password: "password001@",
username: "testName",
mobile: "testMobile",
})
.expect(409)
.expect({ message: "ALREADY_SIGNED_UP" });
});
});
TYPEORM_DATABASE = testDB
"test": "DOTENV_CONFIG_PATH=.env.test jest --setupFiles=dotenv/config --runInBand --detectOpenHandles --forceExit"
Q. How can we test and release program with less time and effort? 🤔
A. Continuous Integration / Continuous Deployment