토비의 스프링 - 6장 (1)
이번 장에서는 AOP 에 대해서 다루게 됩니다. 그런데 현재 이 글을 작성하면서 진행 중인 스프링 스터디 일정에 맞춰 2~3번에 나눠서 글을 작성 하려고 합니다.
그래서 이번 장은 AOP 라는 이름을 가지고 있지만 그 안에서 주로 단위 테스트, 통합 테스트, 고립된 테스트 를 위주로 다루려고 합니다.
- 단위 테스트
- 통합 테스트
- 고립된 테스트
먼저 단위 테스트를 살펴보면 단위 테스트는 특정 영역을 하나의 단위로 잡아 테스트를 진행 하는 걸 의미 합니다. 그 단위는 개발자 혹은 개발팀이 정하게 되고 그런 하나의 단위를 초점으로 둔 테스트 라는 점만 주의한다면 어떤 영역을 잡든 단위 테스트라 할 수 있습니다.
그렇기 때문에 통합 테스트는 이런 두 개 이상의 단위가 결합해서 테스트 해야 할 때를 말하게 됩니다.
단위 테스트를 할지 통합 테스트를 할지가 고민 된다면 몇가지 가이드 라인이 있다고 책에서는 소개 하고 있는데 이를 좀 축약해보려고 합니다.
- 항상 단위 테스트를 먼저 고려합니다. 그 이유는 단위 테스트 들이 모여 통합 테스트를 이루게 되는 경우가 대부분이고 충분한 단위 테스트가 있다면 여러 개의 단위 테스트가 있는 통합 테스트의 부담은 줄어 듭니다.
- 외부 리소스를 사용해야만 하는 테스트는 통합 테스트로 만듭니다. DB 와 연결 되는 UserDAO 와 같은 테스트가 그러합니다.
- 스프링 테스트 컨텍스트 프레임워크를 이용하면 통합 테스트라고 봅니다. 가능하다면 이후에 나오겠지만 스프링의 지원 없이 고립된 테스트로 단위 테스트를 진행합니다. 그러면 테스트 실행 속도 역시 빨라 더 자주 테스트를 진행 할 수 있게 됩니다.
마지막으로 단위 테스트나 통합 테스트나 둘 다 개발자가 자신의 코드를 테스트하기 위해 만든 개발자 테스트 이기 때문에 QA 나 고객에 의한 기능 테스트는 다른 관점에서 바라보는게 중요합니다. (A/B 테스트)
사실 이전에도 한번 이야기 했던 적이 있어 간략하게 이야기 해봤습니다.
고립된 테스트를 진행할 필요성에 대해서 알아보려고 합니다.
책에 나오는 예제 중 하나인 UserService 는 DB 트랜잭션 코드와 비지니스 로직이 함꼐 있는 형태 입니다. 이 코드를 테스트 하려면 DB 트랜잭션 코드 또한 테스트를 해줘야하고 이 과정에서 테스트를 진행 하는데 꽤 시간이 소요 됩니다. 테스트를 할 필요성이 없는건 아니지만 비지니스 로직은 이와 별도로 분리해서 테스트 하면 테스트 시간을 줄일 수가 있게 됩니다.
DB 트랜잭션 로직과 비지니스 로직을 분리하기 위해 책에서는 DI 를 통해 이를 분리하고 있습니다. 책의 코드를 가져 올 수는 없지만 다이어그램을 그리면 다음과 같습니다.
UserService 를 인터페이스로 만들고 DB 트랜잭션 코드를 UserServiceDB 에 구현하고 비지니스 로직은 UserServiceImpl 에 구현합니다. 그 후 UserServiceDB 에서 비지니스 로직인 UserServiceImpl 을 주입받고 DB 트랜잭션 코드 내에서 비지니스 로직을 실행합니다. 이런 UserServiceDB 를 Client 에서 주입받으면 이전과 같은 동작을 합니다. 이때 각 코드들을 분리 했기 때문에 비지니스 로직을 구현한 UserServiceImpl 을 고립된 테스트를 진행 할 수 있게 됩니다. 즉, 테스트 대상을 최대한 분리해 종속되지 않고 영향을 받지 않도록 하는게 고립된 테스트라고 할 수 있습니다.
그리고 분리한 코드가 만약 외부의 의존성이 있는 DB에 저장되어 있는 데이터를 대상으로 하는 코드가 있다면 mock 오브젝트처럼 DB 와 유사한 환경을 가진 클래스를 구축해 테스트를 진행 할 수 있습니다.
이때 책에서는 Mockito 라는 라이브러리를 사용해 mock 오브젝트를 직접 만드는게 아닌 라이브러리를 통해 구축 할 수 있도록 하는 방법을 설명하고 있습니다.
이에 대한 자세한 사용법은 공식 홈페이지 혹은 검색을 통해 찾아보는게 좋습니다.