가능하다면 실제 객체로 테스트 하는게 좋지만 불가능 할 경우
우리는 Mock 이나 Fake 등을 사용합니다.
그러한 Mock 과 Fake를 총칭해서 부르는 말이 TestDouble입니다.
TestDouble의 종류는 무엇이 있는지 알아봅시다.
TestDouble은 실제 객체가 대신 테스트를 수행해주는 역할을 수행하는 객체입니다.
네트워크나, 데이터베이스, 파일 탐색등, 여러가지 테스트를 하기 곤란한 친구들은
TestDouble을 이용해서 테스트를 원할하게 수행 할 수 있습니다.
TestDouble은 총 5가지 종류가 있습니다.
interface Calculator {
fun add(a: Int, b: Int): Int
}
해당 인터페이스에 대한 TestDouble들을 보여드리겠습니다.
가장 기본적인 TestDobule 입니다.
기능을 전혀 구현하지 않은 객체로
인스턴스가 필요하지만 기능은 필요하지 않은 경우 사용합니다.
class DummyCalculator : Calculator {
override fun add(a: Int, b: Int): Int {
TODO()
}
}
Dummy가 동작하는 것처럼 보이게 만든 객체입니다.
단순 하드코딩된 값을 반환합니다.
객체에 특정한 메소드를 적용하기 전과 후의 상태를 확인하는 상태 기반 테스트에 사용합니다.
class StubCalculator : Calculator {
override fun add(a: Int, b: Int): Int {
return 3
}
}
Stub에서 추가적인 정보를 기록할 수 있는 객체입니다.
특정 메소드가 호출되었을때 다른 메소드가 잘 실행 되었는지 확인하는 행위 기반 테스트에 사용합니다.
class SpyCalculator : Calculator {
private var count = 0
override fun add(a: Int, b: Int): Int {
count++
return 3
}
}
동작을 제대로 구현했지만 실제 객체와는 동일하지 않은 객체입니다.
상태 기반 테스트에서 사용되고 Mocking을 필요로 하지않고 가벼워서
구글에서 추천하는 TestDouble입니다.
class FakeCalculator : Calculator {
private var count = 0
override fun add(a: Int, b: Int): Int {
count++
return a + b
}
}
실행하면 정상값을 반환하도록 하는 TestDouble입니다.
행위 기반 테스트에서 사용합니다.
class CalcTest {
@MockK
lateinit var mockCalculator: Calculator
@Before
fun setUp() {
MockKAnnotations.init(this)
}
@Test
fun add_returns_3() {
val a = 1
val b = 2
every { mockCalculator.add(a, b) } returns 3
val result = mockCalculator.add(a, b)
assertEquals(3, result)
}
}
테스트 할 때 최대한 실객체를 사용하려고 하지만 어쩔 수 없는 경우가 많이 있습니다.
그럴때는 TestDouble을 활용해서 테스트를 작성하도록 합시다.
저는 TestDouble이 필요 할 때 Dummy,Fake, Mock을 사용하는데
Spy 나 Stub 같은 Double들도 활용 해봐야겠네요...