1. Service 계층 테스트 시 h2 데이터베이스를 사용하지 않은 이유

src/test/java/wooteco/subway/service/LineServiceTest.java

테스트에서 H2를 사용하지 않은 이유는 무엇인가요?
보통 Spring 테스트 환경에서는 InmemoryDB인 H2를 많이 사용합니다 :)

처음 코드를 짤 때에는 DB 에 저장된 데이터가 롤백되지 않아 임시방편으로 만든 가짜 객체를 사용했었습니다. @JdbcTest 는 각 테스트 메서드마다 실행된 결과가 롤백되는데, @SpringBootTest 는 그렇지 않았습니다.

이후에 리팩토링을 하면서 Service 계층과 같이 중간 단계의 계층에서는 어떻게 테스트를 하는지 찾아보았습니다. 각 계층의 기능이 올바르게 동작하는지 확인하기 위해 진행한 단위 테스트 이므로 다른 계층에 의존하지 않아야 합니다. 즉, Service 계층에서 실행하는 테스트는 Dao 와는 별개로 동작해야 합니다. 따라서 Service 계층에서 h2 데이터베이스를 사용하지 않는 것이 옳다, 라고 생각합니다. 통합 테스트가 아닌 단위 테스트니까요.

제가 임시방편으로 만들어둔 가짜 객체를 지우고 Mockito 라이브러리를 사용해보았습니다. 테스트 방식을 바꾸어보니 @SpringBootTest 를 사용하여 테스트했을 때보다 테스트 실행 시간이 많이 단축되었습니다.

테스트 방식을 바꾸어보면서 느꼈던 나름의 장점을 정리해보았습니다.

  1. Dao 계층에서 내부 수정이 일어나더라도 Service 에는 영향을 끼치지 않는다. => service 에서 사용할 때에는 예상되는 결과를 직접 지정할 뿐 내부 동작에는 영향이 없습니다.
  2. 모든 빈 객체를 컨테이너에 올리는 @SpringBootTest 를 사용했을 때보다 테스트 시간이 단축된다.

하지만 직접 사용해보니 단점이 더 커서 닉이 처음에 말해주셨던 InmemoryDB 를 사용하여 테스트하였습니다. 데이터가 롤백되도록 @JdbcTest 를 붙였고 빈 객체를 가져올 수 없는 것들은 직접 생성하였습니다.

  1. Dao 계층에서 로직이 추가될 경우 Service 에 추가해야 하는 경우가 있다. => 내부 로직 수정이 아닌 기능을 구현하면서 DB 관련 로직이 추가 될 경우 대부분의 테스트코드를 수정해야 했습니다.
  2. 가짜 객체로 선언한 객체의 실제 동작을 정확하게 예측해야 한다. => 테스트 시 모든 상황을 가정하여 결과를 정확하게 예측해야 한다는 점이 부담이 되었습니다.
  3. mockito 라이브러리의 주의사항을 모두 알고있어야 한다. => 익숙하지 않은 외부 라이브러리에 대한 사용법을 정확하게 알고 있어야 했습니다. 가끔은 코드작성보다 mockito 라이브러리에서 발생한 오류를 찾는데 시간을 더 쏟기도 했습니다.

2. 외부 계층(Controller) 에서 도메인이 노출될 경우의 단점

src/main/java/wooteco/subway/service/LineService.java

외부 계층(Controller)과 소통할 때 도메인이 그대로 노출되고 있는데요, 이렇게 되면 어떤 문제가 있을 수 있을까요? :)

Controller 는 사용자와 상호작용하는 프레젠테이션 계층 입니다. View 와 밀접하게 맞닿아 있습니다. View 는 사용자에게 노출되는 공간이므로 사소한 수정 요구사항이 많습니다. 보여지는 부분을 수정하기 위해서 프레젠테이션 계층인 Controller 까지 확인해야 하는데, Controller 에서 도메인을 호출한다면 수정 시 확인해야 하는 범위가 늘어납니다. 수정사항이 많은 View 영역과 다른 계층을 분리시키기 위해 Controller 를 도메인 객체로 주고받던 것에서 DTO 객체로 수정하였습니다.