programming4 MIN READ

[소프트웨어 테스트] 06. 테스트 더블과 모의 객체

[소프트웨어 테스트] 06. 테스트 더블과 모의 객체

소프트웨어 테스트 시리즈의 글입니다.

stub, fake, mock, dummy 등 테스트 더블과 모의객체를 잘 다뤄서 좋은 테스트를 작성하려면 어떻게 하면 될까?

여러 클래스끼리 서로 의존하는게 보통이기때문에 모든것이 함께 잘 동작하는지 함께 확인하고 싶은것이 인지상정이나.. 격리된 방식으로 테스트 하는 방법에 대해 논의해보자. 모든 의존성을 함께 테스트 하려면 너무 느리거나, 너무 힘들거나, 너무 많은 일을 해야할 수 있음. 따라서 의존성을 사용하지 않고 테스트 하는 방법이 필요. 테스트 터블(test double) : 구성요소 A는 아니지만 구성요소A를 모방하는 객체를 생성하고, 테스트 맥락에 따라 A처럼 행동하도록 할 수 있음. 이러한 테스트 더블을 사용한다면 실제 객체에 대한 의존성을 줄일 수 있다. 장점

  • 더 큰 제어권을 가짐. (ex. 쉽게 예외를 던지게 하거나. 원하는 값을 던지게 할 수 있음)
  • 시뮬레이션 객체는 빠름. (ex. web통신, DB 통신.. 느린 행위를 안해도됨)
  • 클래스간 상호작용을 반영 가능. (계약, 경계를 적용..)

6.1 시뮬레이션 방식

6.1.1 Dummy

테스트 대상 클래스에 전달되지만 절대 사용되지 않는 객체

6.1.2 Fake

시뮬레이션하려는 클래스같이 동작하지만, 훨씬 단순한 방식으로 동작하는 객체

6.1.3 Stub

테스트 과정에서 수행된 호출에 대해 하드 코딩된 응답을 제공.(구현체 X)

6.1.4 Mock

내가 설정한 응답을 돌려줄 수 있는 객체. 단 모든 상호작용을 저장해 단언문에 활용 가능. (ex. 메서드는 어떤 특정 매개변수로 호출되지 않는다. 등등) 클래스 상호작용에 대한 통찰력을 제공

6.1.5 스파이

의존성을 감시하는 객체. 실체 객체를 감싸서 그 행동을 관찰함. 모든 상호작용을 기록함.

6.2 모의 객체 프레임워크

https://site.mockito.org

  • mock(<class>)
  • when(<mock>.<method>).thenReturn(<value>)
  • verify(<mock>).<method>

6.3 현업에서의 모의 객체

모범사례에 대해 논의해보자 언제 모의 객체를 사용해야 하고 언제 사용하지 말아야하는가?

6.3.1 모의 객체의 단점

  • 잘못 사용하면, 코드가 아니라 모의객체를 테스트하게됨.
    • 테스트를 덜 현실적으로 만듦.
    • 모의객체가 대규모로 잘 동작하게 하려면 계약을 신경써서 설계해야함.
  • 모의객체를 사용한 테스트는 자연스럽게 모의 객체를 사용하지 않은 테스트보다 코드와 결합하게됨
    • 테스트 대상 클래스에 대한 정보를 무 많이 알게됨
    • 테스트와 제품 코드간 결합도가 증가됨
    • 하지만 오히려 결합되어서 변경시에 테스트가 깨진다면 좋은거 아닐까 싶기도.. (저자생각)

6.3.2 모의해야하는 대상과 하지 말아야 하는 대상

모의하면 좋은 대상

  • 의존성이 너무 느린경우
  • 의존성이 외부 인프라와 통신하는 경우
  • 의존성을 시뮬레이션 하기 힘든 경우

모의하지 말아야 하는 대상

  • Entity : 비즈니스 개념을 표현하는 클래스. 이걸 모의하는데 공수가 더 많이들수도. (무거운 엔티티는 예외)
  • Native library : ex. Arraylist
  • Utility method : ex. String.format
  • 충분히 단순한 의존성

6.3.3 날짜 및 시간 wrapper

날짜 및 시간 연산은 흔하게 일어나기때문에 전용 클래스로 감싸고, 해당 래퍼 클레스를 모킹하여 사용하는것이 좋다

6.3.4 소유하지 않은 것을 모의하기

소유하지 않은 클래스(ex. LocalDate)도 모의할 수 있음. 하지만 모범사례는 소유하지 않은 것은 모의하지 않는것이 좋음

  • 라이브러리 변경 발생시에도 테스트가 깨지지 않을수 있음
  • 외부 라이브러리를 모의하는것은 꽤 어려운 일임

6.3.5 모의에 관한 외부 의견

구글엔지니어는 이렇게 일한다의 의견에 대하여 저자의 생각

  • 테스트 더블을 사용하려면 시스템이 테스트 가능성을 가지도록 살계해야함. : ㅇㅇ동의
  • 실제 구현에 충실하게 테스트 더블을 구축하는 일은 어렵지만 가능한 그렇게 해야함. : ㅇㅇ
  • 고립성보다 현실성이 낫다. 가능한 실제 구현을 선택하자 : ㅇㅇ 동의함 하지만 느리거나 비결정적이면 모의하자.
  • 실제 구현을 사용하는 일이 불가능하거나 비용이 들면 mock보다 fake 객체 사용 : 비동의. fake객체가 실제구현과 동일한지 확신 불가능하다 생각.
  • 모의를 너무 많이 사용하면 위험하다. : ㅇㅇ
  • 모의할때는 상호작용 테스트보다 상태 테스트가 낫다 : 상호작용이 중요하면 상호작용 테스트를, 처리 결과가 중요하다면 상태 변화 테스트를 하자.
  • 구체화된 상호작용 테스트는 피하자. : ㅇㅇ동의
  • 좋은 상호작용 테스트를 작성하려면 설계할때 엄격한 지침이 필요 : ㅇㅇ동의