2020-8-18 Express, Supertest 환경분리
배경
- 자바, 스프링에서 개발을 하다가 Express로 개발하면서 가장 어려웠던 부분은 테스트였다. 각 테스트가 끝나면 자동으로 종료가 잘 안됬다. 무엇보다도 개발데이터베이스와 테스트데이터베이스의 분리가 잘 안됬다 !!!
테스트코드
import {MongoMemoryServer} from 'mongodb-memory-server';
describe('Sample Test', () => {
let mongoServer;
beforeAll(async () => {
mongoServer = new MongoMemoryServer();
const URI = await mongoServer.getUri();
await mongoose.connect(URI, {
useNewUrlParser: true,
useUnifiedTopology: true
}, () => {
console.log(`success to memory db`)
});
});
afterEach(async () => {
const collections = await mongoose.connection.db.collections();
for (let collection of collections)
await collection.deleteMany();
})
afterAll(async (done) => {
mongoose.disconnect(done)
})
test('회원 가입 테스트', async (done) => {
request(app)
.post('/users')
.send({
email: 'test@email.com',
password: '123457',
confirmPassword: '123457'
})
.expect(201)
.end((err, res) => {
if (err) return done(err);
expect(res.body.email).toBe('test@email.com');
done();
})
})
});
- Describe단위로 testsuite를 분리했다. 여기서 beforeAll을 이용해서 처음 테스트가 실행될때, 몽고디비의 메모리서버를 구동시키고 mongoose를 이용해서 연결했다. JS문법이 익숙하지 않아서 mongoose와 db 커넥션을 맺는게 많이 헷갈렸다. 레퍼런스에도 다 mongodb와 직접적으로 커넥션을 맺고 있어서 더욱 힘들었다.
- afterEach를 통해 각 테스트케이스가 완료되면 collections를 순회하면서 데이터를 초기화 한다.
- afterAll에서 DB와 커넥션을 끊는다.
환경설정
// jest.config.js
module.exports = {
preset: "@shelf/jest-mongodb",
testEnvironment: "node",
}
// jest-mongdb-config.js
module.exports = {
mongodbMemoryServerOptions: {
binary: {
version: '4.0.3',
skipMD5: true
},
autoStart: false,
instance: {
db: 'test'
}
}
}
- jest-mongodb-config파일에서 테스트에서 사용할 MongoMemoryServer에 대한 옵션을 설정한다. 지금은 테스트파일이 하나이지만 향후 여러개로 될때 공통속성으로 유용할거 같다.
- 데이터베이스와 테스트간의 환경분리를 위해 jest옵션에서 preset을 지정한다. jest-mongodb를 사용하면 jest를 사용할때 미리 mongodb에 대한 설정을 한다고 간단하게 나와있다. 여기서도 teardown, global설정을 할 수 있는데, 아직은 적용하지 못했다. 추후 차근차근 분리를 시킬 예정이다.
그밖의 문제
- 포트충돌 : 테스트 케이스를 여러개 돌릴때 포트충돌나는 경우가 발생했다. 원인을 찾아보니 jest에서 여러개를 돌리기때문에 –maxWorkers=1 옵션을 통해 한번에 1개만 돌아가도록 설정했다.
- 테스트종료안됨 : 테스트가 종료되지 않고 계속 돌아갔다. –forceExit옵션을 통해 테스트가 끝나면 강제적으로 종료시켰다.
느낀점
- 작년에도 Express를 하면서 Supertest와 express의 테스트환경 분리하는게 어려웠었다. 그때는 지금보다 시간적으로 해결하지 못해서 결국에는 testdb를 아예 따로 만들었었다. 오늘 작성한 코드에서는 테스트 데이터베이스를 분리할 수 있었다. jest옵션에 나온 global과 teardown옵션도 적용해봐야겠지만 추후 적용할 예정이다. 스프링에서는 test스코프와 일반 runtime 스코프에서 환경을 분리할 수 있고 테스트를 돌리기 쉬웠는데, node를 하면서 개념을 알지만 디버깅이나 코드로 녹여내는게 힘들었다. 하루종일 코드를 작성했다 지웠다를 반복하면서 다양한 생각들이 들었지만 그래도 큰 문제는 해결할 수 있었다.
Written on August 18, 2020