지금까지 서버 가동에 필요한 모든 코드를 app.js에 포함했다면,
이제는 app.js와 server.js로 분리하여 관리한다
router, middleware 관련 코드만 남겨두고
app을 리턴하는 createApp 함수 생성
const express = require("express");
const cors = require("cors");
const morgan = require("morgan");
const { routes } = require("./src/routes");
const createApp = () => {
const app = express();
app.use(express.json());
app.use(cors());
app.use(morgan("combined"));
app.use(routes);
return app;
};
module.exports = { createApp };
app은 app.js에서 만들어 놓은 createApp 함수 활용
AppDataSource.initialize(), app.listen()을 담고 있는 startServer 함수 실행
require("dotenv").config();
const { createApp } = require("./app");
const { AppDataSource } = require("./src/models/data-source");
const startServer = async () => {
const app = createApp();
const PORT = process.env.PORT;
await AppDataSource.initialize();
app.listen(PORT, () => {
console.log(`Listening on Port ${PORT}`);
});
};
startServer();
서버를 켤 때는 server.js 실행
테스트 코드에서는 createApp 함수의 리턴값인 app만 활용
테스트를 진행할 때, 실제 DB를 활용하면 문제가 발생하기 때문에
테스트 전용 환경 변수를 따로 관리해야 함
# .env.test
DB_TYPE=mysql
DB_HOST=localhost
DB_PORT=3306
DB_USERNAME=root
DB_PASSWORD=dbpassword
DB_NAME=dbname
jest를 이용하게 되면 DB커넥션에 활용할 수 있다
$ npm i --save-dev supertest
해당 파일을 config로 테스트할 수 있도록 package.json/scripts에 명령어 추가
"scripts": {
"test": "DOTENV_CONFIG_PATH=.env.test jest --setupFiles=dotenv/config"
},
$ npm i --save-dev supertest
const request = require("supertest");
jest 설치 및 적용(supertest)
// tests/user.test.js
// supertest의 request에 app을 담아 활용하기 위해 createApp 함수를 불러옵니다.
const { createApp } = require("../app");
// DB와의 커넥션을 위해 DataSource 객체를 불러옵니다.
const { myDataSource } = require("../src/models/data-source");
supertest 사용
describe("Sign Up", () => {
let app;
beforeAll(async () => {
// 모든 테스트가 시작하기 전(beforeAll)에 app을 만들고, DataSource를 이니셜라이징 합니다.
app = createApp();
await AppDataSource.initialize();
});
afterAll(async () => {
// 테스트 데이터베이스의 불필요한 데이터를 전부 지워줍니다.
await AppDataSource.query(`TRUNCATE users`);
// 모든 테스트가 끝나게 되면(afterAll) DB 커넥션을 끊어줍니다.
await AppDataSource.destroy();
});
DB와의 연결 및 불필요한 데이터 삭제
테스트 이후 DB 연결 끊어주기
test("FAILED: invalid email", async () => {
// supertest의 request를 활용하여 app에 테스트용 request를 보냅니다.
await request(app)
.post("/users/signup") // HTTP Method, 엔드포인트 주소를 작성합니다.
.send({ email: "wrongEmail", password: "password001@" }) // body를 작성합니다.
.expect(400) // expect()로 예상되는 statusCode, response를 넣어 테스트할 수 있습니다.
.expect({ message: "invalid email!" });
});
// 다음과 같이 본인이 작성한 코드에 맞춰 다양한 케이스를 모두 테스트해야 합니다.
// 그래야 의도에 맞게 코드가 잘 작성되었는지 테스트 단계에서부터 확인할 수 있습니다!
test("SUCCESS: created user", async () => {
await request(app)
.post("/users/signup")
.send({ email: "wecode001@gmail.com", password: "password001@" })
.expect(201);
});
test("FAILED: duplicated email", async () => {
await request(app)
.post("/users/signup")
.send({ email: "wecode001@gmail.com", password: "password001@" })
.expect(409)
.expect({ message: "duplicated email" });
});
});
HTTP 메소드, 보내야 하는 정보, 예상 결과에 맞게 테스트 진행