📌 테스트 방법1. Service단 테스트를 둘로 나누는 방법박진형의 생각?2. Service단 Mock 테스트만 작성혜빈병연 3. Service단 Mock 없이 테스트 작성 (By 곽동운)
위 링크를 읽고 나서 피어난 의문들입니다!
전제가 일단 실제 서비스 클래스는
Repository
에 의존적입니다.위의 UserService를 테스트 할 때 → 실제로 테스트 할 때 어떻게 적용을 해야 되는지?
📌 테스트 방법
동운님이 진형의 말을 이해한 바로는 아래와 같음
1. Service단 테스트를 둘로 나누는 방법
- TDD는 기능이 정상적으로 동작하는지에 대한 테스트
- BDD는 시나리오 동작으로 예상한 결과값을 반환 되는지를 테스트 (MockTest)
A가 10,000원을 B에게 계좌이체를 하면 이체 결과가 화면에 출력된다.
TDD는 Repository를 이용해서 비지니스 로직 안에서의 실제 기능들이 수행되는지를 확인.
- A의 계좌는 10,000원이 감소했다.
- B의 계좌는 10,000원이 증가했다.
BDD에서는 Repository의 의존을 끊어버리고, 실제로 Service단의 메서드를 수행했을 때,
올바른 값을 반환하는지에 초점을 두고 테스트를 하기 위해 Mock을 사용
- 계좌이체 로직을 수행 했을 때, 이체 결과가 의도한 바로 반환 되는지에 초점 (Repository의 각각 결과값은 Mock으로 설정)
박진형의 생각?
동운님의 생각 “BDD에서는 Repository의 의존을 끊어버리고, 실제로 Service단의 메서드를 수행했을 때,
올바른 값을 반환하는지에 초점을 두고 테스트를 하기 위해 Mock을 사용한다는 것인가?
- 계좌이체 로직을 수행 했을 때, 이체 결과가 의도한 바로 반환 되는지에 초점 (Repository의 각각 결과값은 Mock으로 설정)”
→ 저의 생각 : 그것보다는 의도한 바로 반환되는지에 대한 초점은 TDD고, BDD는 그 메서드 속에서 행위들이 시나리오 토대로 빠짐 없이 수행되고 있는가? 에 초점을 맞춘 테스트가 아닌가?
https://tv.kakao.com/channel/3693125/cliplink/414004682 영상 7분 10초에서 12분 10초까지 말하고 있는듯?
TDD 테스트는 테스트 하고자 하는 메서드가 입력값에 대하여 올바른 값을 뱉고 있는지 확인
//given
String newName = “ newName”;
String new Hobby = “newHobby”;
//when
userService.update(newName, newHobby)
User foundUser = user.findById(userId);
//then
assertThat ..값을 검증…
반면 BDD는 내가 짠 시나리오 대로 메서드들이 수행되고 있는지에 대한 초첨.. 서비스 메서드 내에서 수행되는 각 메서드의 결과 값은 비교적 중요하지 않음 결과 값은 내가 Given단계에서 정해줄 것…
예를 들어
userService.update() {
행동 1.
행동 2.
행동 3.
return 결과
} 라는 Service의 메서드를 테스트 하고자 했을 때,
//given
given(행동1).willReturn(결과 1)
given(행동2).willReturn(결과 2)
given(행동3).willReturn(결과 3)
//when
userService.update(newName, newHobby)
//then
verify(행동 1을 1회 수행했는지?)
verify(행동 2를 1회 수행했는지?)
verify(행동 3를 1회 수행했는지?)
와 같이 시나리오대로 메서드 내 행위들이 누락없이 수행되고 있는가?를 테스트가 주 목적 처럼 보인다.
정리하자면, BDD의 목적은 시나리오에 대한 테스트(행위를 수행을 했는지 안했는지)이고
TDD의 목적은 정확한 결과값을 내는 코드를 짰는지 안짰는지에 대한 테스트라고 생각이 든다.
- update를 한 결과 값이 어떤지 테스트하는 것은 TDD 단위테스트
- update를 하는 동안 어떤 행위들이 빠짐없이 수행됐는지 테스트하는 것은 BDD 테스트
어떤 행위들이 빠짐없이 수행됐는지 테스트 하기위해서는 Mocking을 통해서 다른 외부 의존을 끊고, 그 메서드의 행위에 대해서만 집중할 수 있다.
→Mocking을 하지 않으면 다른 외부 의존으로 부터 완전하게 분리가 되지 않아 시나리오만을 검증하고 싶어도 어려움이 있다?
- update를 하는 과정 속에서 어떤 중요한 부분을 놓쳤다고 쳤을때, 값만 제대로 출력 됐다고 해서 이게 올바른 코드라고 볼 수 있는가?(TDD는 BDD가 채워주는 부분을 가지고 있지않다.)
- 우리가 정해놓은 시나리오 대로 수행을 했는지 확인이 필요한게 아닌가?(BDD가 필요하다?)
- 우리가 시나리오 대로 행위를 수행한다고 해도, 그 행위 자체의 로직이 잘못됐다면 올바른 코드라고 볼 수 있는가?(BDD는 TDD가 채워주는 부분을 가지고 있지 않다.)
- 이 행위가 정말 올바르게 작동하는지 확인하는 테스트가 필요한게 아닌가? (TDD가 필요하다?)
그렇다면 내가 정말 필요하다고 생각되는 테스트 들은
- 단위 테스트
- 서비스 레이어만 따로 테스트하기위해 모킹을하는 BDD 테스트?
- 시나리오에 오류와는 별개로 서비스 메서드가 모든 함수를 수행하고나서 올바른 값을 반환을 하는지 테스트 하는, 서비스 레이어 통합 테스트?
그래서 나는 도메인 레이어의 단위 테스트, 컨버터의 테스트를 따로 먼저 짜고, BDD 테스트를 따로 짜고, 통합테스트를 따로 짰다?!
- 제가 말한 부분을 실제 코드로 작성한 자료가 있어 공유합니다.
- unit, integration 패키지의 코드를 확인해보면 될 것 같습니다.
2. Service단 Mock 테스트만 작성
Repository의 의존성만 없애고 그대로 테스트
Service단에서 사용되는 해당 Repository와 다른 Service 객체의 메서드는
해당 클래스의 테스트(존재한다면..)에서 이미 검증된 것들이니 이를 Mock으로 결과값을 미리 정의
혜빈
- 저는 단위 테스트를 한다는 생각으로 mock을 사용했습니다. 해당 클래스의 의존 관계를 다 끊어야지 오로지 해당 레이어가 해야 하는 작업에 대해서만 테스트 하는 거라 생각합니다. 레이어 마다 mock 테스트를 진행하고, 이후 컨트롤러에서 의존 관계를 살려 테스트하면 되는게 아닐까 라는 생각을 했습니다. ⇒ 이렇게 생각해보니 두 가지 테스트를 다 진행하는 방법에 의견이 쏠리는 것 같네요. 어떤 목적으로 테스트를 할 건지, 현재 상황과 팀 컨벤션에 맞게 적용하는게 좋은 것 같습니다. (mock은 구현이 조금 바뀌면 박살 날 수 도 있으니 ..>? )
병연
- service는 오직 mock test만 하는게 아니라 mock도 하고 전체적인 테스트도 하는 것이 좋다고 생각합니다. 그 이유는 클라이언트에 대한 요청이 3-tier에 의해서 종속적으로 작동하기 때문에 각 레이어별로 단위(목 테스트)가 이루어져야 버그 지점을 명확히 파악할 수 있기 때문입니다.
3. Service단 Mock 없이 테스트 작성 (By 곽동운)
🤔 의문 : 왜 Service에서 Mock을 써야하지? → Repository의 의존성을 없애야 하는가?
Controller 레이어
- 실제로 Client 에게 Request 받고 결과를 Response 하는 역할
그래서 내부 로직과는 상관없이 Client에게 요청에 대한 올바른 값으로 반환하는것에만 초점을 두기 위해서
Controller 테스트에서는 Mock을 사용하는 걸로 이해 했었습니다.
하지만 Service단의 경우에는 실제로 데이터 변경 행위가 일어나는 곳이라고 생각하는데…
그렇다면 다른 서비스나 Repository를 이용해서 어떤 행위를 했을 때,
1. 각각의 행위들로 인해서 값들이 결과적으로 모두 적절하게 변경 되었는가
2. 그리고 반환 값이 있다면 올바르게 반환값들을 반환하고 있는가
위를 모두 포함한 것이 Service단의 하나의 메서드의 테스트라고 생각하고 있습니다.
(결과적으로 여기서는 Mock을 사용해서 이렇게 수행될것이다. 라고 가정하면 안된다?)
그렇다면 Mock으로 의존성을 없애지 않고, 의존한 상태에서 테스트하는게 맞지 않을까? 와 함께
Service단의 테스트 자체가 BDD + TDD를 포함한 테스트라고 생각했습니다.
- BDD : 요청한 행위에 대해 올바르게 값을 반환하는가 (어떤 상황에 어떤 값이 주어졌고, 결과로 이러한 값을 반환한다.)
- TDD : 요청한 행위에 대해서 올바르게 기능들이 다 수행되었는가. (요청에 의해 실제 데이터가 각각의 기능이 수행되어 올바르게 변경되었다.)
📌 진형님 댓글 답변?

저는 BDD와 TDD라는 것이 개념적으로만 다른 것이지,
서로 다른 테스트들을 연계해서 저렇게 BDD영역까지 테스트를 모두 해야 된다? 라고 이해 했던것 같습니다.
(2번은 Service단 안에 [다른 Service단의 메서드를 사용하는 경우의 그 메서드])
… 생각해보니? 1번이 그냥 Controller.. 2번이 Service 메서드 인거 같네요…? 🤔